项目描述:
设计一个文本文件压缩工具,哈夫曼编码是一种常用的数据压缩技术,对数据文件进行哈夫曼编码可大大缩短文件的传输长度,提高信道利用率及传输效率。要求采用哈夫曼编码原理,统计文本文件中字符出现的频率,以频率作为权值,对文件进行哈夫曼编码以达到压缩文件的目的,再用哈夫曼编码进行译码解压缩。
功能实现:
-
主菜单主界面与功能一览
-
统计词频:统计待压缩的文本文件中各字符出现的频率,以频率为权值建立哈夫曼树,并将该哈夫曼树保存到文件HufTree.dat中。
-
查询该文本文件的字符:能按照频率排名降序或字符ascii码升序后的查询、分页查询、区间查询、查询倒数第N个
-
编码:根据哈夫曼树(保存在HufTree.dat中)对每个字符进行哈夫曼编码,并将字符编码保存到HufCode.txt文件中。
-
压缩:根据哈夫曼编码,将源文件进行编码得到压缩文件CodeFile.dat。
-
解压:将CodeFile.dat文件利用哈夫曼树译码解压,恢复为源文件。
-
退出系统
EasyX版:
#include<iostream>
#include<graphics.h>
#include<easyx.h>
#include<conio.h>
using namespace std;
typedef struct Chardata {
char data;
long long int num;
} chardata;
typedef struct Hflist {
char data;
long long int num;
char *encoding;
} hflist;
typedef struct Node1 {
int rt;
long long int num;
char data;
struct Node1 *lchild,*rchild;
} Node;
//频率升序
int compare1(const void *a, const void *b) {
return (*(chardata*)a).num - (*(chardata*)b).num;
}
//字符ASCII升序
int compare2(const void *a, const void *b) {
return (*(chardata*)a).data - (*(chardata*)b).data;
}
//频率降序
int compare3(const void *a, const void *b) {
return (*(chardata*)b).num - (*(chardata*)a).num;
}
//字符ASCII降序
int compare4(const void *a, const void *b) {
return (*(chardata*)b).data - (*(chardata*)a).data;
}
ExMessage msg = {0};
int inArea(int mx, int my, int x, int y, int w, int h) {
if (mx > x && mx < x + w && my > y && my < y + h)return 1;
else return 0;
}
int button(int x, int y, int w, int h, const char* text) {
int hSpace = (w - textwidth(text)) / 2;
int vSpace = (h - textheight(text)) / 2;
if (inArea(msg.x, msg.y, x, y, w, h))setfillcolor(RGB(204, 232, 255));
else setfillcolor(WHITE);
fillroundrect(x, y, x + w, y + h, 5, 5);
outtextxy(x + hSpace, y + vSpace, text);
if (msg.message == WM_LBUTTONDOWN && inArea(msg.x, msg.y, x, y, w, h))return 1;
else return 0;
}
void prompt(char *txt) {
int font_size = 40;
initgraph(250, 250, EX_SHOWCONSOLE);
setbkcolor(WHITE);
setlinecolor(BLACK);
setlinestyle(PS_SOLID, 1);
settextcolor(BLACK);
setbkmode(TRANSPARENT);
while (textwidth(txt) > 212 || textheight(txt) > 40 && font_size > 5) {
font_size--;
settextstyle(font_size, 0, _T("楷体"));
}
msg.message = 0;
while (1) {
BeginBatchDraw();
cleardevice();
setfillcolor(WHITE);
peekmessage(&msg, EX_MOUSE);
if (kbhit()) {
char ch = getch();
if (ch == '\r')break;
}
fillroundrect(18, 50, 18 + 212, 50 + 40, 5, 5);
outtextxy(18 + (212 - textwidth(txt)) / 2, 50 + (40 - textheight(txt)) / 2, txt);
if (button(100, 150, 60, 25, _T("确认")))break;
EndBatchDraw();
msg.message = 0;
}
closegraph();
}
int three__interface(char string1[][100], int o[4]) {
initgraph(700, 432, EX_SHOWCONSOLE);
setbkcolor(WHITE);
setlinecolor(BLACK);
setlinestyle(PS_SOLID, 3);
settextcolor(BLACK);
setbkmode(TRANSPARENT);
int result = 0;
while (1) {
BeginBatchDraw();
cleardevice();
setfillcolor(WHITE);
settextstyle(o[0], 0, _T("楷体"));
fillroundrect(150, 20, 150 + 400, 20 + 50, 5, 5);
outtextxy(150 + (400 - textwidth(string1[0])) / 2, 20 + (50 - textheight(string1[0])) / 2, string1[0]);
peekmessage(&msg, EX_MOUSE);
settextstyle(o[1], 0, _T("楷体"));
if (button(250, 100, 200, 60, _T(string1[1]))) {
result = 1;
break;
}
settextstyle(o[2], 0, _T("楷体"));
if (button(250, 190, 200, 60, _T(string1[2]))) {
result = 2;
break;
}
settextstyle(o[3], 0, _T("楷体"));
if (button(250, 280, 200, 60, _T(string1[3]))) {
result = 3;
break;
}
EndBatchDraw();
msg.message = 0;
}
closegraph();
msg.message = 0;
return result;
}
int pagQuery_interface(chardata *a, int num, char *txt, int *flag) {
char str1[100] = "频率", str2[100] = "字符";
char string1[100] = "上一页", string2[100] = "返回", string3[100] = "下一页";
initgraph(800, 220 + 60 * num, EX_SHOWCONSOLE);
setbkcolor(WHITE);
setlinecolor(BLACK);
setlinestyle(PS_SOLID, 1);
settextcolor(BLACK);
setbkmode(TRANSPARENT);
settextstyle(28, 0, _T("楷体"));
int result = 0;
while (1) {
BeginBatchDraw();
cleardevice();
setfillcolor(WHITE);
fillroundrect(200, 20, 200 + 400, 20 + 40, 5, 5);
outtextxy(200 + (400 - textwidth(txt)) / 2, 20 + (40 - textheight(txt)) / 2, txt);
fillroundrect(100, 80, 100 + 240, 80 + 40, 5, 5);
outtextxy(100 + (240 - textwidth(str2)) / 2, 80 + (40 - textheight(str2)) / 2, str2);
fillroundrect(460, 80, 460 + 240, 80 + 40, 5, 5);
outtextxy(460 + (240 - textwidth(str1)) / 2, 80 + (40 - textheight(str1)) / 2, str1);
peekmessage(&msg, EX_MOUSE);
if (kbhit()) {
char ch = getch();
if (ch == '\r')break;
}
for (int i = 1; i <= num; i++) {
if (a[i - 1].num == 0)continue;
fillroundrect(100, 80 + i * 60, 100 + 240, 80 + i * 60 + 40, 5, 5);
outtextxy(100 + (240 - textwidth(a[i - 1].data)) / 2, 80 + i * 60 + (40 - textheight(a[i - 1].data)) / 2, a[i - 1].data);
char temp[100] = {'\0'};
sprintf(temp, "%d", a[i - 1].num);
fillroundrect(460, 80 + i * 60, 460 + 240, 80 + i * 60 + 40, 5, 5);
outtextxy(460 + (240 - textwidth(temp)) / 2, 80 + i * 60 + (40 - textheight(temp)) / 2, temp);
}
if (flag[0] == 0) {
if (button(35, 140 + num * 60, 220, 40, _T(string1))) {
result = -1;
break;
}
}
if (button(290, 140 + num * 60, 220, 40, _T(string2))) {
result = 0;
break;
}
if (flag[1] == 0) {
if (button(545, 140 + num * 60, 220, 40, _T(string3))) {
result = 1;
break;
}
}
EndBatchDraw();
msg.message = 0;
}
closegraph();
msg.message = 0;
return result;
}
void charnum(char *str, long long int num) {
sprintf(str, "%lld", num);
}
void filerenamecheck(char *a, char *fileExtension) {
char b[10000] = {'\0'};
strncpy(b, a, sizeof(b) -1);
strncat(b, fileExtension, sizeof(b) - strlen(b) -1);
FILE *file = fopen(b, "r");
if (!file)return ;
fclose(file);
long long int count = 1;
char c[100] = {'\0'}, d[100] = {'\0'};
while (1) {
c[0] = '(';
c[1] = '\0';
charnum(d, count);
strcat(c, d);
long long int length = strlen(c), temp_length = strlen(fileExtension);
c[length] = ')';
c[length + 1] = '\0';
b[0] = '\0';
strncpy(b, a, sizeof(b) -1);
strcat(b, c);
char e[100] = {'\0'};
strncpy(e, b, sizeof(e) -1);
strcat(e, fileExtension);
file = fopen(e, "r");
if (!file) {
a[0] = '\0';
strncpy(a, b, strlen(b) +1);
fclose(file);
return ;
}
fclose(file);
count++;
}
}
void savehufTree_1(FILE *a, Node *root) {
if (root == NULL)return ;
fprintf(a, "%d %d %d ", root->rt, root->num, root->data);
if (root->lchild != NULL)fprintf(a, "%d %d %d ", root->lchild->rt, root->lchild->num, root->lchild->data);
else fprintf(a, "-1 -1 -1 ");
if (root->rchild != NULL)fprintf(a, "%d %d %d\n", root->rchild->rt, root->rchild->num, root->rchild->data);
else fprintf(a, "-1 -1 -1\n");
savehufTree_1(a, root->lchild);
savehufTree_1(a, root->rchild);
}
int savehfuTree(Node *root, int size, char *c) {
FILE *a;
char b[100] = "HufTree";
char d[10] = ".dat";
filerenamecheck(b, d);
strcat(b, ".dat");
strcpy(c, b);
a = fopen(b, "w");
if (a == NULL) {
char str[100] = {'\0'};
sprintf(str, "文件%s打开失败!", b);
perror(str);
prompt(str);
return -1;
}
fprintf(a, "%d\n", size);
savehufTree_1(a, root);
fclose(a);
return 0;
}
Node* nodecreate(char data, int num) {
Node *a = (Node*)malloc(sizeof(Node));
if (a == NULL) {
char o1[100] = "节点创建失败!";
perror(o1);
prompt(o1);
return NULL;
}
a->rt = -1;
a->data = data;
a->num = num;
a->lchild = NULL, a->rchild = NULL;
return a;
}
int hfencordlist_1(Node* root, hflist* a, long long int *current_size, long long int size, char b[], long long int top) {
if (*current_size >= size || root == NULL)return -1;
if (root->data != '\0') {
a[*current_size].data = root->data;
a[*current_size].num = root->num;
if (top == 0 && size == 1) {
top = 1;
b[0] = '0';
}
char *temp = (char*)malloc((top + 1) * sizeof(char));
if (temp == NULL) {
char str1[100] = "数组temp内存分配失败!";
perror(str1);
prompt(str1);
return -1;
}
temp[top] = '\0';
memcpy(temp, b, top);
a[*current_size].encoding = temp;
(*current_size)++;
}
b[top] = '0', b[top + 1] = '\0';
hfencordlist_1(root->lchild, a, current_size, size, b, top + 1);
b[top] = '1', b[top + 1] = '\0';
hfencordlist_1(root->rchild, a, current_size, size, b, top + 1);
return 0;
}
hflist* hfencordlist(Node *root, int num) {
hflist *a = (hflist*)malloc(num * sizeof(hflist));
if (a == NULL) {
char o1[100] = "数组a内存分配失败!";
perror(o1);
prompt(o1);
return NULL;
}
long long int size = 0;
char b[300] = {'\0'};
int temp = hfencordlist_1(root, a, &size, num, b, 0);
if (temp == -1) {
free(a);
return NULL;
}
return a;
}
Node* buildTree(long long int size, Node **record, long long int *returnsize) {
if (size < 2)return record[0];
long long int top = size;
long long int count1 = 0;
Node *root = NULL;
for (int i = 0; i < size - 1; i++) {
int min = 0;
for (int j = 0; j < top; j++) {
if (record[j]->num < record[min]->num)min = j;
}
int secmin = (min == 0) ? 1 : 0;
for (int j = 0; j < top; j++) {
if (j == min)continue;
if (record[j]->num < record[secmin]->num)secmin = j;
}
if (record[min]->rt == -1)record[min]->rt = count1++;
if (record[secmin]->rt == -1)record[secmin]->rt = count1++;
root = nodecreate('\0', record[min]->num + record[secmin]->num);
if (root == NULL)return NULL;
root->lchild = record[min], root->rchild = record[secmin];
if (root->rt == -1)root->rt = count1++;
int temp1 = min > secmin ? secmin : min;
int temp2 = min > secmin ? min : secmin;
record[temp1] = root;
record[temp2] = record[top - 1];
top--;
}
*returnsize = count1;
return root;
}
long long int CalculatedLength(hflist const *a, int const num) {
long long int length = 0;
for (int i = 0; i < num; i++) {
length += (long long int)strlen(a[i].encoding) * (long long int)a[i].num;
}
return length;
}
chardata *statisticalTxt(char const *FileName, long long int *returnSize) {
FILE *a;
a = fopen(FileName, "r");
if (a == NULL) {
char o1[100] = {'\0'};
sprintf(o1, "文件%s打开失败!", FileName);
perror(o1);
prompt(o1);
return NULL;
}
chardata *b = (chardata*)calloc(256, sizeof(chardata));
if (b == NULL) {
char o1[100] = "数组b内存分配失败!";
perror(o1);
prompt(o1);
fclose(a);
return NULL;
}
char temp = '\0';
*returnSize = 0;
while (fscanf(a, "%c", &temp) != EOF) {
if (b[(unsigned char)temp].num == 0) {
b[(unsigned char)temp].data = temp;
(*returnSize)++;
}
b[(unsigned char)temp].num++;
}
fclose(a);
chardata *c = (chardata*)malloc(*returnSize * sizeof(chardata));
if (c == NULL) {
char o1[100] = "数组c内存分配失败!";
perror(o1);
prompt(o1);
fclose(a);
free(b);
return NULL;
}
for (int i = 0, j = 0; i < 256; i++) {
if (b[i].num > 0) {
c[j] = b[i];
j++;
}
}
qsort(c, *returnSize, sizeof(chardata), compare1);
free(b);
return c;
}
char* nameinput(char *txt) {
initgraph(700, 432, EX_SHOWCONSOLE);
setbkcolor(RGB(18, 237, 241));
char input[10000] = {'\0'};
int length = 0;
bool isActive = true;
msg.message = 0;
while (1) {
if (kbhit()) {
char ch = getch();
if (ch == '\r' && length > 0) {
isActive = false;
break;
} else if (ch == '\b') {
if (length > 0) {
input[--length] = '\0';
}
} else if (ch >= 32 && ch <= 126) {
if (length < sizeof(input) -1) {
input[length++] = ch;
input[length] = '\0';
}
}
}
BeginBatchDraw();
cleardevice();
setfillcolor(WHITE);
settextcolor(BLACK);
setlinestyle(PS_SOLID, 2);
setlinecolor(BLACK);
settextcolor(BLACK);
setbkmode(TRANSPARENT);
fillrectangle(200, 30, 500, 70);
settextstyle(20, 0, _T("楷体"));
outtextxy(200 + (300 - textwidth(txt)) / 2, 30 + (40 - textheight(txt)) / 2, txt);
fillrectangle(100, 150, 600, 200);
settextstyle(28, 0, _T("Consolas"));
outtextxy(105, 161, input);
static int counter = 0;
if (isActive && (++counter % 30) < 15) {
int w = textwidth(input);
line(105 + w, 161, 105 + w, 188);
}
EndBatchDraw();
Sleep(20);
}
char *returnstring = (char*)malloc((length + 1) * sizeof(char));
if (returnstring == NULL) {
char o1[100] = "数组returnstring内存分配失败!";
perror(o1);
prompt(o1);
return NULL;
}
strcpy(returnstring, input);
returnstring[length] = '\0';
closegraph();
msg.message = 0;
return returnstring;
}
char *filenaming(char *fileExtension) {
char *s, s0[10000] = "请输入期望文件名:", s1[1000] = "警告:该文件名不可用!";
while (1) {
int flag = 0;
s = nameinput(s0);
if (s == NULL)return NULL;
for (int i = 0; s[i] != '\0'; i++) {
if (s[i] == '\\' || s[i] == '/' || s[i] == ':' || s[i] == '*' ||
s[i] == '?' || s[i] == '"' || s[i] == '<' || s[i] == '>' || s[i] == '|') {
flag = 1;
break;
}
}
if (!flag)break;
else prompt(s1);
}
char *a = (char*)malloc((strlen(s) +5) * sizeof(char));
if (a == NULL) {
char o1[100] = "数组a分配失败!";
perror(o1);
prompt(o1);
return NULL;
}
strcpy(a, s);
filerenamecheck(a, fileExtension);
strcat(a, fileExtension);
a[strlen(a)] = '\0';
return a;
}
int compress_1(char const *FileName, hflist const *a, int const num, char *treefile) {
FILE *b,*d;
long long int length = CalculatedLength(a, num);
hflist *list = (hflist*)malloc(256 * sizeof(hflist));
if (list == NULL) {
char o1[100] = "数组list内存分配失败!";
perror(o1);
prompt(o1);
return -1;
}
for (int i = 0; i < num; i++) {
int index = 0;
index = (unsigned char)a[i].data;
list[index] = a[i];
}
b = fopen(FileName, "r");
if (b == NULL) {
char o1[100] = {'\0'};
sprintf(o1, "文件%s打开失败!", FileName);
perror(o1);
prompt(o1);
return -1;
}
char y[10] = ".dat";
char *x = filenaming(y);
if (x == NULL)return -1;
d = fopen(x, "wb");
if (d == NULL) {
char o1[100] = {'\0'};
sprintf(o1, "文件%s打开失败!", x);
perror(o1);
prompt(o1);
return -1;
}
int length1 = strlen(treefile);
fwrite(&length1, sizeof(int), 1, d);
fwrite(treefile, sizeof(char), length1, d);
fwrite(&length, sizeof(long long int), 1, d);
int bit = 0;
char temp = '\0';
char data = 0;
while (fscanf(b, "%c", &temp) != EOF) {
if (list[(unsigned char)temp].encoding == NULL)continue;
int c = strlen(list[(unsigned char)temp].encoding);
for (int i = 0; i < c; i++) {
if (bit >= 8) {
fputc(data, d);
bit = 0;
data = 0;
}
if (list[(unsigned char)temp].encoding[i] == '1') {
data |= (1 << (7 - bit));
}
bit++;
}
}
free(x);
fputc(data, d);
fclose(b);
fclose(d);
return 0;
}
Node *rebuildTree(char *treefile) {
FILE *x;
x = fopen(treefile, "r");
if (x == NULL) {
char o1[100] = {'\0'};
sprintf(o1, "文件%s打开失败!", treefile);
perror(o1);
prompt(o1);
return NULL;
}
int count1 = 0;
fscanf(x, "%d\n", &count1);
Node **record = (Node**)malloc((count1 + 1) * sizeof(Node*));
if (record == NULL) {
char o1[100] = "数组record内存分配失败!";
perror(o1);
prompt(o1);
return NULL;
}
for (int i = 0; i <= count1; i++) {
record[i] = NULL;
}
for (int i = 0; i < count1; i++) {
int a[3] = {0}, b[3] = {0}, c[3] = {0};
fscanf(x, "%d %d %d %d %d %d %d %d %d\n", &a[0],
&a[1], &a[2], &b[0], &b[1], &b[2], &c[0], &c[1], &c[2]);
if (record[a[0]] == NULL) {
Node*temp = nodecreate((char)a[2], a[1]);
if (temp == NULL)return NULL;
temp->rt = a[0];
record[a[0]] = temp;
}
if (b[0] != -1 && record[b[0]] == NULL) {
Node*temp = nodecreate((char)b[2], b[1]);
if (temp == NULL)return NULL;
temp->rt = b[0];
record[b[0]] = temp;
}
if (c[0] != -1 && record[c[0]] == NULL) {
Node*temp = nodecreate((char)c[2], c[1]);
if (temp == NULL)return NULL;
temp->rt = c[0];
record[c[0]] = temp;
}
if (b[0] != -1)record[a[0]]->lchild = record[b[0]];
if (c[0] != -1)record[a[0]]->rchild = record[c[0]];
}
Node *root = record[count1 - 1];
free(record);
fclose(x);
return root;
}
char *filePathcheck(char *a) {
int length = strlen(a), j = 0;
char *b = (char*)malloc(2 * length * sizeof(char));
if (b == NULL) {
char o1[100] = "数组b内存分配失败!";
perror(o1);
prompt(o1);
return NULL;
}
for (int i = 0; i < length; i++) {
if (a[i] == '\\')b[j++] = a[i];
b[j++] = a[i];
}
b[j] = '\0';
free(a);
return b;
}
char *name() {
char b[1000] = "请输入文件名或文件路径:";
char *s = nameinput(b);
if (s == NULL)return NULL;
char *a = filePathcheck(s);
return a;
}
void freeTree(Node *root) {
if (root == NULL)return ;
Node* l = root->lchild,*r = root->rchild;
free(root);
freeTree(l);
freeTree(r);
}
int decode() {
int flag = 0;
char *Filename = name();
if (Filename == NULL)return 1;
FILE *a,*b;
a = fopen(Filename, "rb");
if (a == NULL) {
char o[1000] = {'\0'};
sprintf(o, "文件%s不存在!", Filename);
prompt(o);
fclose(a);
return 1;
}
char c[10] = ".txt";
char *Filename1 = filenaming(c);
if (Filename1 == NULL) {
fclose(a);
return 1;
}
b = fopen(Filename1, "w");
if (b == NULL) {
char x[1000] = {'\0'};
sprintf(x, "文件%s创建失败!", Filename1);
prompt(x);
fclose(a);
fclose(b);
return 1;
}
int length1 = 0;
long long int length = 0;
fread(&length1, sizeof(int), 1, a);
char *treefile = (char*)malloc((length1 + 1) * sizeof(char));
if (treefile == NULL) {
char o1[100] = "数组treefile内存分配失败!";
perror(o1);
prompt(o1);
return 1;
}
fread(treefile, sizeof(char), length1, a);
fread(&length, sizeof(long long int), 1, a);
long long int size = (length + 7) / 8;
char *data = (char*)malloc(size * sizeof(char));
if (data == NULL) {
char o1[100] = "数组data内存分配失败!";
perror(o1);
prompt(o1);
return 1;
}
fread(data, sizeof(char), size, a);
Node *root = rebuildTree(treefile),*current_node = NULL;
if (root == NULL)flag = 1;
current_node = root;
for (int i = 0; i < size && flag != 1; i++) {
int bit = 7;
while (bit >= 0) {
if (current_node->rchild == NULL) {
fprintf(b, "%c", current_node->data);
current_node = root;
}
if ((data[i] >> bit) & 1) {
current_node = current_node->rchild;
} else current_node = current_node->lchild;
bit--;
}
}
free(treefile);
free(Filename1);
free(data);
fclose(a);
fclose(b);
freeTree(root);
return flag;
}
int savehfulist(hflist *list, int num) {
FILE *a;
char b[100] = "HufCode";
char c[10] = ".txt";
filerenamecheck(b, c);
strcat(b, ".txt");
a = fopen(b, "w");
if (a == NULL) {
char str[100] = {'\0'};
sprintf(str, "文件%s打开失败!", b);
perror(str);
prompt(str);
return -1;
}
for (int i = 0; i < num; i++) {
fprintf(a, "%d %d %s\n", list[i].data, list[i].num, list[i].encoding);
}
fclose(a);
return 0;
}
void freelist(hflist *a, int num) {
for (int i = 0; i < num; i++) {
free(a[i].encoding);
}
}
int compress_main() {
long long int num = 0, count1 = 0;
char *filename = name();
chardata *b = statisticalTxt(filename, &num);
if (b == NULL)return 1;
Node *root = NULL;
Node **record = (Node**)malloc(num * sizeof(Node*));
if (record == NULL) {
char o1[100] = "数组record内存分配失败!";
perror(o1);
prompt(o1);
free(b);
return 1;
}
for (int i = 0; i < num; i++) {
Node *temp = nodecreate(b[i].data, b[i].num);
if (temp == NULL)return 1;
record[i] = temp;
}
root = buildTree(num, record, &count1);
if (root == NULL)return 1;
hflist *c = hfencordlist(root, num);
if (c == NULL) {
free(b);
return 1;
}
char treefile[100] = {'\0'};
int temp = savehfuTree(root, count1, treefile);
if (temp == -1) {
free(b);
return 1;
}
int temp1 = compress_1(filename, c, num, treefile);
if (temp1 == -1) {
free(b);
return 1;
}
int temp2 = savehfulist(c, num);
if (temp2 == -1) {
free(b);
return 1;
}
free(b);
free(filename);
freeTree(root);
free(record);
freelist(c, num);
free(c);
return 0;
}
int object_print() {
char a[4][100] = {"请选择排序对象:", "频率", "字符ASCII值", "返回"};
int b[4] = {32, 32, 32, 32};
int result = three__interface(a, b);
return result;
}
int SortOrder() {
char a[4][100] = {"请选择排序顺序:", "升序", "降序", "返回"};
int b[4] = {32, 32, 32, 32};
int result = three__interface(a, b);
return result;
}
void chardataHandle(chardata **a, int object, int order, int num) {
if (object == 1 && order == 1) {
qsort(*a, num, sizeof(chardata), compare1);
}
if (object == 2 && order == 1) {
qsort(*a, num, sizeof(chardata), compare2);
}
if (object == 1 && order == 2) {
qsort(*a, num, sizeof(chardata), compare3);
}
if (object == 2 && order == 2) {
qsort(*a, num, sizeof(chardata), compare4);
}
}
int reasonableJudgment(int max) {
int a = 0;
while (1) {
char str[100] = "请输入位序:";
char *b = nameinput(str);
if (b == NULL)return -1;
a = atoi(b);
if (a <= 0 || a > max) {
char c[100] = "数据不合理,请重新输入!";
prompt(c);
} else break;
}
return a;
}
int selection(int a(), int *data) {
while (1) {
int b = a();
if (b == 1) {
*data = 1;
break;
} else if (b == 2) {
*data = 2;
break;
} else return 1;
}
return 0;
}
int BasicSelection(int *object, int *order) {
while (1) {
int a = selection(SortOrder, order);
if (a == 1)return 1;
int b = selection(object_print, object);
if (b != 1)break;
}
return 0;
}
int sequence(chardata *a, int flag, int num, int way) {
int object = 1, order = 1;
if (flag == 1 && BasicSelection(&object, &order))return 1;
chardataHandle(&a, object, order, num);
int c = reasonableJudgment(num);
if (c == -1)return -1;
char str[1000] = {'\0'}, numchar[100] = {'\0'};
if (way == 1) {
sprintf(str, "顺序第%d个字符是%c。", c, a[c - 1].data);
} else {
sprintf(str, "逆序第%d个字符是%c。", c, a[num - c].data);
}
prompt(str);
return 0;
}
int four_interface(char a[][100]) {
initgraph(700, 432, EX_SHOWCONSOLE);
setbkcolor(WHITE);
setlinecolor(BLACK);
setlinestyle(PS_SOLID, 3);
settextcolor(BLACK);
setbkmode(TRANSPARENT);
settextstyle(32, 0, _T("楷体"));
int result = 0;
while (1) {
BeginBatchDraw();
cleardevice();
setfillcolor(WHITE);
fillroundrect(150, 20, 150 + 400, 20 + 50, 5, 5);
outtextxy(150 + (400 - textwidth(a[0])) / 2, 20 + (50 - textheight(a[0])) / 2, a[0]);
peekmessage(&msg, EX_MOUSE);
if (button(250, 100, 200, 50, _T(a[1]))) {
result = 1;
break;
}
if (button(250, 180, 200, 50, _T(a[2]))) {
result = 2;
break;
}
if (button(250, 260, 200, 50, _T(a[3]))) {
result = 3;
break;
}
if (button(250, 340, 200, 50, _T(a[4]))) {
result = 4;
break;
}
EndBatchDraw();
msg.message = 0;
}
closegraph();
msg.message = 0;
return result;
}
int five_interface(char string1[6][100]) {
initgraph(700, 432, EX_SHOWCONSOLE);
setbkcolor(WHITE);
setlinecolor(BLACK);
setlinestyle(PS_SOLID, 3);
settextcolor(BLACK);
setbkmode(TRANSPARENT);
int result = 0;
while (1) {
BeginBatchDraw();
cleardevice();
setfillcolor(WHITE);
fillroundrect(150, 20, 150 + 400, 20 + 50, 5, 5);
outtextxy(150 + (400 - textwidth(string1[0])) / 2, 20 + (50 - textheight(string1[0])) / 2, string1[0]);
peekmessage(&msg, EX_MOUSE);
settextstyle(28, 0, _T("楷体"));
if (button(250, 100, 200, 40, _T(string1[1]))) {
result = 1;
break;
}
settextstyle(32, 0, _T("楷体"));
if (button(250, 170, 200, 40, _T(string1[2]))) {
result = 2;
break;
}
settextstyle(28, 0, _T("楷体"));
if (button(250, 240, 200, 40, _T(string1[3]))) {
result = 3;
break;
}
settextstyle(32, 0, _T("楷体"));
if (button(250, 310, 200, 40, _T(string1[4]))) {
result = 4;
break;
}
if (button(250, 380, 200, 40, _T(string1[5]))) {
result = 5;
break;
}
EndBatchDraw();
msg.message = 0;
}
closegraph();
msg.message = 0;
return result;
}
int charQuery(chardata *a, int num) {
while (1) {
char string1[6][100] = {"请选择查询顺序:", "顺序(默认选择)", "顺序", "逆序(默认选择)", "逆序", "返回"};
int b = five_interface(string1), temp = 0;
if (b == 1) {
temp = sequence(a, 0, num, 1);
if (temp == -1)return 1;
if (!temp)break;
} else if (b == 2) {
temp = sequence(a, 1, num, 1);
if (temp == -1)return 1;
if (!temp)break;
} else if (b == 3) {
temp = sequence(a, 0, num, 2);
if (temp == -1)return 1;
if (!temp)break;
} else if (b == 4) {
temp = sequence(a, 1, num, 2);
if (temp == -1)return 1;
if (!temp)break;
} else return 1;
}
return 0;
}
int intervalQuery_print() {
char a[4][100] = {"请选择查询对象:", "字符频率区间", "字符ASCII值区间", "返回"};
int b[4] = {32, 32, 24, 32};
int result = three__interface(a, b);
return result;
}
int *findinterval(int *returnsize, chardata *a, int num, int frist, int last, int flag) {
int *b = (int*)malloc(num * sizeof(int));
if (b == NULL) {
char o1[100] = "数组b内存分配失败!";
perror(o1);
prompt(o1);
return NULL;
}
*returnsize = 0;
for (int i = 0; i < num; i++) {
if (flag == 1 && a[i].num <= last && a[i].num >= frist)b[(*returnsize)++] = i;
if (flag == 2 && a[i].data <= last && a[i].data >= frist)b[(*returnsize)++] = i;
}
return b;
}
int pagQueryprint(int num) {
int a = 0;
while (1) {
char str0[100] = "请输入每页展示数量:", str1[100] = "数据不合理,请重新输入!";
char *b = nameinput(str0);
if (b == NULL)return -1;
a = atoi(b);
if (a <= num && a > 0)break;
else prompt(str1);
}
return a;
}
void pagHandle(chardata *a, chardata *b, int count1, int num, int pagnum, int *flag) {
memset(b, 0, count1 * sizeof(chardata));
for (int i = (pagnum - 1) * count1, j = 0; i < pagnum * count1 && i < num; i++, j++) {
b[j] = a[i];
}
if (pagnum == 1)flag[0] = 1;
if (num - pagnum * count1 <= 0)flag[1] = 1;
}
int allQuery(chardata*a, int num) {
char str[100] = "字符频率查询";
int order = SortOrder(), object = object_print();
chardataHandle(&a, object, order, num);
int count1 = pagQueryprint(num), pagnum = 1;
if (count1 == -1)return 1;
chardata *b = (chardata*)malloc(count1 * sizeof(chardata));
if (b == NULL) {
char o1[100] = "数组b内存分配失败!";
perror(o1);
prompt(o1);
return 1;
}
while (1) {
int flag[2] = {0};
pagHandle(a, b, count1, num, pagnum, flag);
int c = pagQuery_interface(b, count1, str, flag);
if (c != 0 && (!(pagnum == 1 && c == -1)))pagnum += c;
else break;
}
free(b);
return 0;
}
int intervalpag(chardata *a, int num, char *str) {
int count1 = pagQueryprint(num), pagnum = 1;
chardata *b = (chardata*)malloc(count1 * sizeof(chardata));
if (b == NULL) {
char o1[100] = "数组b内存分配失败!";
perror(o1);
prompt(o1);
return -1;
}
while (1) {
int flag[2] = {0};
pagHandle(a, b, count1, num, pagnum, flag);
int c = pagQuery_interface(b, count1, str, flag);
if (c != 0 && (!(pagnum == 1 && c == -1)))pagnum += c;
else break;
}
return 0;
}
int interval(chardata *a, int num, int b) {
int frist = 0, last = 0;
char str0[100] = "数据不合理,请重新输入!";
while (1) {
char str[100] = "请输入区间起始位置:";
char *temp = nameinput(str);
if (temp == NULL)return -1;
frist = atoi(temp);
if (frist > 0 && frist < num)break;
else prompt(str0);
}
while (1) {
char str1[100] = "请输入区间末尾位置:";
char *temp = nameinput(str1);
if (temp == NULL)return -1;
last = atoi(temp);
if (((b == 1 && last <= a[0].num) || (b == 2 && last <= 256)) && last > frist)break;
else prompt(str0);
}
int size = 0;
int *c = findinterval(&size, a, num, frist, last, b);
if (c == NULL)return -1;
char str2[100] = "该区间无符合值!";
if (size == 0)prompt(str2);
else {
char str3[1000] = {'\0'}, temp[100] = {'\0'};
if (b == 1) {
sprintf(str3, "字符频率从%d到%d有:", frist, last);
} else {
sprintf(str3, "字符ASCII值从%d到%d有:", frist, last);
}
chardata *d = (chardata*)malloc(size * sizeof(chardata));
if (d == NULL) {
char o1[100] = "数组d内存分配失败!";
perror(o1);
prompt(o1);
return -1;
}
for (int i = 0; i < size; i++) {
d[i] = a[c[i]];
}
int e = intervalpag(d, size, str3);
if (e == -1)return -1;
}
free(c);
return 0;
}
int intervalQuery(chardata *a, int num) {
qsort(a, num, sizeof(chardata), compare3);
while (1) {
int b = intervalQuery_print();
if (b > 0 && b < 3) {
if (!interval(a, num, b))break;
} else return 1;
}
return 0;
}
int statistics_main() {
char *a = name();
int v = 0;
long long int num = 0;
chardata *b = statisticalTxt(a, &num);
if (b == NULL)return -1;
while (1) {
char string1[5][100] = {"请选择查询方式:", "单字符查询", "区间查询", "查询全部", "返回"};
int c = four_interface(string1);
if (c == 1)charQuery(b, num);
else if (c == 2)intervalQuery(b, num);
else if (c == 3) {
v = allQuery(b, num);
if (v)return -1;
} else return 1;
}
free(a);
return 0;
}
int main() {
//freopen("nul", "w", stderr);
while (1) {
char txt[5][100] = {"文本文件压缩", "压缩文件", "解压文件", "字符频率查询", "退出"};
int a = four_interface(txt);
char a1[1000] = "成功!", a2[1000] = "失败!", a3[1000] = "请输入有效选择!";
if (a == 1) {
if (!compress_main())prompt(a1);
else prompt(a2);
} else if (a == 2) {
if (!decode())prompt(a1);
else prompt(a2);
} else if (a == 3) {
if (statistics_main() == -1)prompt(a2);
} else if (a == 4)break;
else prompt(a3);
}
return 0;
}
C语言版:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct Chardata {
char data;
long long int num;
} chardata;
typedef struct Hflist {
char data;
long long int num;
char *encoding;
} hflist;
typedef struct Node1 {
int rt;
long long int num;
char data;
struct Node1 *lchild,*rchild;
} Node;
//频率升序
int compare1(const void *a, const void *b) {
return (*(chardata*)a).num - (*(chardata*)b).num;
}
//字符ASCII升序
int compare2(const void *a, const void *b) {
return (*(chardata*)a).data - (*(chardata*)b).data;
}
//频率降序
int compare3(const void *a, const void *b) {
return (*(chardata*)b).num - (*(chardata*)a).num;
}
//字符ASCII降序
int compare4(const void *a, const void *b) {
return (*(chardata*)b).data - (*(chardata*)a).data;
}
void charnum(char *str, long long int num) {
sprintf(str, "%lld", num);
}
void filerenamecheck(char *a, char *fileExtension) {
char b[10000] = {'\0'};
strncpy(b, a, sizeof(b) -1);
strncat(b, fileExtension, sizeof(b) - strlen(b) -1);
FILE *file = fopen(b, "r");
if (!file)return ;
fclose(file);
long long int count = 1;
char c[100] = {'\0'}, d[100] = {'\0'};
while (1) {
c[0] = '(';
c[1] = '\0';
charnum(d, count);
strcat(c, d);
long long int length = strlen(c), temp_length = strlen(fileExtension);
c[length] = ')';
c[length + 1] = '\0';
b[0] = '\0';
strncpy(b, a, sizeof(b) -1);
strcat(b, c);
char e[100] = {'\0'};
strncpy(e, b, sizeof(e) -1);
strcat(e, fileExtension);
file = fopen(e, "r");
if (!file) {
a[0] = '\0';
strncpy(a, b, strlen(b) +1);
fclose(file);
return ;
}
fclose(file);
count++;
}
}
void savehufTree_1(FILE *a, Node *root) {
if (root == NULL)return ;
fprintf(a, "%d %d %d ", root->rt, root->num, root->data);
if (root->lchild != NULL)fprintf(a, "%d %d %d ", root->lchild->rt, root->lchild->num, root->lchild->data);
else fprintf(a, "-1 -1 -1 ");
if (root->rchild != NULL)fprintf(a, "%d %d %d\n", root->rchild->rt, root->rchild->num, root->rchild->data);
else fprintf(a, "-1 -1 -1\n");
savehufTree_1(a, root->lchild);
savehufTree_1(a, root->rchild);
}
void savehfuTree(Node *root, int size, char *c) {
FILE *a;
char b[100] = "HufTree";
char d[10] = ".dat";
filerenamecheck(b, d);
strcat(b, ".dat");
strcpy(c, b);
a = fopen(b, "w");
fprintf(a, "%d\n", size);
savehufTree_1(a, root);
fclose(a);
}
int enterNumbers() {
char temp[100000] = {'\0'};
scanf("%99999s", temp);
return atoi(temp);
}
Node* nodecreate(char data, int num) {
Node *a = (Node*)malloc(sizeof(Node));
a->rt = -1;
a->data = data;
a->num = num;
a->lchild = NULL, a->rchild = NULL;
return a;
}
void hfencordlist_1(Node* root, hflist* a, long long int *current_size, long long int size, char b[], long long int top) {
if (*current_size >= size || root == NULL)return ;
if (root->data != '\0') {
a[*current_size].data = root->data;
a[*current_size].num = root->num;
if (top == 0 && size == 1) {
top = 1;
b[0] = '0';
}
char *temp = (char*)malloc((top + 1) * sizeof(char));
temp[top] = '\0';
memcpy(temp, b, top);
a[*current_size].encoding = temp;
(*current_size)++;
}
b[top] = '0', b[top + 1] = '\0';
hfencordlist_1(root->lchild, a, current_size, size, b, top + 1);
b[top] = '1', b[top + 1] = '\0';
hfencordlist_1(root->rchild, a, current_size, size, b, top + 1);
}
hflist* hfencordlist(Node *root, int num) {
hflist *a = (hflist*)malloc(num * sizeof(hflist));
if (a == NULL)return NULL;
long long int size = 0;
char b[300] = {'\0'};
hfencordlist_1(root, a, &size, num, b, 0);
return a;
}
Node* buildTree(long long int size, Node **record, long long int *returnsize) {
if (size < 2)return record[0];
long long int top = size;
long long int count1 = 0;
Node *root = NULL;
for (int i = 0; i < size - 1; i++) {
int min = 0;
for (int j = 0; j < top; j++) {
if (record[j]->num < record[min]->num)min = j;
}
int secmin = (min == 0) ? 1 : 0;
for (int j = 0; j < top; j++) {
if (j == min)continue;
if (record[j]->num < record[secmin]->num)secmin = j;
}
if (record[min]->rt == -1)record[min]->rt = count1++;
if (record[secmin]->rt == -1)record[secmin]->rt = count1++;
root = nodecreate('\0', record[min]->num + record[secmin]->num);
root->lchild = record[min], root->rchild = record[secmin];
if (root->rt == -1)root->rt = count1++;
int temp1 = min > secmin ? secmin : min;
int temp2 = min > secmin ? min : secmin;
record[temp1] = root;
record[temp2] = record[top - 1];
top--;
}
*returnsize = count1;
return root;
}
long long int CalculatedLength(hflist const *a, int const num) {
long long int length = 0;
for (int i = 0; i < num; i++) {
length += (long long int)strlen(a[i].encoding) * (long long int)a[i].num;
}
return length;
}
chardata *statisticalTxt(char const *FileName, long long int *returnSize) {
FILE *a;
a = fopen(FileName, "r");
if (a == NULL) {
perror("文件打开失败");
return NULL;
}
chardata *b = (chardata*)calloc(256, sizeof(chardata));
if (b == NULL) {
perror("数组b内存分配失败");
fclose(a);
return NULL;
}
char temp = '\0';
*returnSize = 0;
while (fscanf(a, "%c", &temp) != EOF) {
if (b[(unsigned char)temp].num == 0) {
b[(unsigned char)temp].data = temp;
(*returnSize)++;
}
b[(unsigned char)temp].num++;
}
fclose(a);
chardata *c = (chardata*)malloc(*returnSize * sizeof(chardata));
if (c == NULL) {
perror("数组c内存分配失败");
fclose(a);
free(b);
return NULL;
}
for (int i = 0, j = 0; i < 256; i++) {
if (b[i].num > 0) {
c[j] = b[i];
j++;
}
}
qsort(c, *returnSize, sizeof(chardata), compare1);
free(b);
return c;
}
char *filenaming(char *fileExtension) {
char s[10000] = {'\0'};
while (1) {
int flag = 0;
printf("请输入期望文件名:");
memset(s, '\0', sizeof(s));
scanf("%9999s", s);
for (int i = 0; s[i] != '\0'; i++) {
if (s[i] == '\\' || s[i] == '/' || s[i] == ':' || s[i] == '*' ||
s[i] == '?' || s[i] == '"' || s[i] == '<' || s[i] == '>' || s[i] == '|') {
flag = 1;
break;
}
}
if (!flag)break;
else printf("警告:该文件名不可用!\n");
}
char *a = (char*)malloc((strlen(s) +5) * sizeof(char));
if (a == NULL) {
perror("数组分配失败");
return NULL;
}
strcpy(a, s);
filerenamecheck(a, fileExtension);
strcat(a, fileExtension);
a[strlen(a)] = '\0';
return a;
}
void compress_1(char const *FileName, hflist const *a, int const num, char *treefile) {
FILE *b,*d;
long long int length = CalculatedLength(a, num);
hflist *list = (hflist*)malloc(256 * sizeof(hflist));
for (int i = 0; i < num; i++) {
int index = 0;
index = (unsigned char)a[i].data;
list[index] = a[i];
}
b = fopen(FileName, "r");
char y[10] = ".dat";
char *x = filenaming(y);
d = fopen(x, "wb");
int length1 = strlen(treefile);
fwrite(&length1, sizeof(int), 1, d);
fwrite(treefile, sizeof(char), length1, d);
fwrite(&length, sizeof(long long int), 1, d);
int bit = 0;
char temp = '\0';
char data = 0;
while (fscanf(b, "%c", &temp) != EOF) {
if (list[(unsigned char)temp].encoding == NULL)continue;
int c = strlen(list[(unsigned char)temp].encoding);
for (int i = 0; i < c; i++) {
if (bit >= 8) {
fputc(data, d);
bit = 0;
data = 0;
}
if (list[(unsigned char)temp].encoding[i] == '1') {
data |= (1 << (7 - bit));
}
bit++;
}
}
free(x);
fputc(data, d);
fclose(b);
fclose(d);
}
Node *rebuildTree(char *treefile) {
FILE *x;
x = fopen(treefile, "r");
int count1 = 0;
fscanf(x, "%d\n", &count1);
Node **record = (Node**)malloc((count1 + 1) * sizeof(Node*));
for (int i = 0; i <= count1; i++) {
record[i] = NULL;
}
for (int i = 0; i < count1; i++) {
int a[3] = {0}, b[3] = {0}, c[3] = {0};
fscanf(x, "%d %d %d %d %d %d %d %d %d\n", &a[0],
&a[1], &a[2], &b[0], &b[1], &b[2], &c[0], &c[1], &c[2]);
if (record[a[0]] == NULL) {
Node*temp = nodecreate((char)a[2], a[1]);
temp->rt = a[0];
record[a[0]] = temp;
}
if (b[0] != -1 && record[b[0]] == NULL) {
Node*temp = nodecreate((char)b[2], b[1]);
temp->rt = b[0];
record[b[0]] = temp;
}
if (c[0] != -1 && record[c[0]] == NULL) {
Node*temp = nodecreate((char)c[2], c[1]);
temp->rt = c[0];
record[c[0]] = temp;
}
if (b[0] != -1)record[a[0]]->lchild = record[b[0]];
if (c[0] != -1)record[a[0]]->rchild = record[c[0]];
}
Node *root = record[count1 - 1];
free(record);
fclose(x);
return root;
}
char *filePathcheck(char *a) {
int length = strlen(a), j = 0;
char *b = (char*)malloc(2 * length * sizeof(char));
for (int i = 0; i < length; i++) {
if (a[i] == '\\')b[j++] = a[i];
b[j++] = a[i];
}
b[j] = '\0';
return b;
}
char *name() {
char s[10000] = {'\0'};
scanf("%9999s", s);
char *a = filePathcheck(s);
return a;
}
void freeTree(Node *root) {
if (root == NULL)return ;
Node* l = root->lchild,*r = root->rchild;
free(root);
freeTree(l);
freeTree(r);
}
int decode() {
int flag = 0;
char *Filename = name();
FILE *a,*b;
a = fopen(Filename, "rb");
if (a == NULL) {
perror("文件不存在");
fclose(a);
return 1;
}
char c[10] = ".txt";
char *Filename1 = filenaming(c);
if (Filename1 == NULL) {
fclose(a);
return 1;
}
b = fopen(Filename1, "w");
if (b == NULL) {
perror("文件创建失败");
fclose(a);
fclose(b);
return 1;
}
int length1 = 0;
long long int length = 0;
fread(&length1, sizeof(int), 1, a);
char *treefile = (char*)malloc((length1 + 1) * sizeof(char));
fread(treefile, sizeof(char), length1, a);
fread(&length, sizeof(long long int), 1, a);
long long int size = (length + 7) / 8;
char *data = (char*)malloc(size * sizeof(char));
fread(data, sizeof(char), size, a);
Node *root = rebuildTree(treefile),*current_node = NULL;
if (root == NULL)flag = 1;
current_node = root;
for (int i = 0; i < size && flag != 1; i++) {
int bit = 7;
while (bit >= 0) {
if (current_node->rchild == NULL) {
fprintf(b, "%c", current_node->data);
current_node = root;
}
if ((data[i] >> bit) & 1) {
current_node = current_node->rchild;
} else current_node = current_node->lchild;
bit--;
}
}
free(treefile);
free(Filename1);
free(data);
fclose(a);
fclose(b);
freeTree(root);
return flag;
}
void savehfulist(hflist *list, int num) {
FILE *a;
char b[100] = "HufCode";
char c[10] = ".txt";
filerenamecheck(b, c);
strcat(b, ".txt");
a = fopen(b, "w");
for (int i = 0; i < num; i++) {
fprintf(a, "%d %d %s\n", list[i].data, list[i].num, list[i].encoding);
}
fclose(a);
}
void freelist(hflist *a, int num) {
for (int i = 0; i < num; i++) {
free(a[i].encoding);
}
}
int compress_main() {
long long int num = 0, count1 = 0;
char *filename = name();
chardata *b = statisticalTxt(filename, &num);
if (b == NULL)return 1;
Node *root = NULL;
Node **record = (Node**)malloc(num * sizeof(Node*));
if (record == NULL) {
perror("数组record内存分配失败");
free(b);
return 1;
}
for (int i = 0; i < num; i++) {
Node *temp = nodecreate(b[i].data, b[i].num);
record[i] = temp;
}
root = buildTree(num, record, &count1);
hflist *c = hfencordlist(root, num);
if (c == NULL) {
free(b);
return 1;
}
char treefile[100] = {'\0'};
savehfuTree(root, count1, treefile);
compress_1(filename, c, num, treefile);
savehfulist(c, num);
free(b);
free(filename);
freeTree(root);
free(record);
freelist(c, num);
free(c);
return 0;
}
int choose() {
printf("请选择:");
char a[10000] = {'\0'};
scanf("%9999s", a);
int length = strlen(a);
if (length == 1) {
if (a[0] == 'A' || a[0] == 'a')return 1;
if (a[0] == 'B' || a[0] == 'b')return 2;
if (a[0] == 'C' || a[0] == 'c')return 3;
if (a[0] == 'D' || a[0] == 'd')return 4;
if (a[0] == 'E' || a[0] == 'e')return 5;
}
return -1;
}
void print_main() {
printf("%*s####文本文件压缩####\n", 10, " ");
printf("%*sA.压缩文件\n", 14, " ");
printf("%*sB.解压文件\n", 14, " ");
printf("%*sC.统计字符频率\n", 14, " ");
printf("%*sD.退出\n", 14, " ");
}
void object_print() {
printf("请选择排序对象:\n");
printf("%*sA.频率\n", 14, " ");
printf("%*sB.字符ASCII值\n", 14, " ");
printf("%*sC.返回\n", 14, " ");
}
void SortOrder() {
printf("请选择排序顺序:\n");
printf("%*sA.升序\n", 14, " ");
printf("%*sB.降序\n", 14, " ");
printf("%*sC.返回\n", 14, " ");
}
void chardataHandle(chardata **a, int object, int order, int num) {
if (object == 1 && order == 1) {
qsort(*a, num, sizeof(chardata), compare1);
}
if (object == 2 && order == 1) {
qsort(*a, num, sizeof(chardata), compare2);
}
if (object == 1 && order == 2) {
qsort(*a, num, sizeof(chardata), compare3);
}
if (object == 2 && order == 2) {
qsort(*a, num, sizeof(chardata), compare4);
}
}
int reasonableJudgment(int max) {
int a = 0;
while (1) {
printf("请输入位序:");
a = enterNumbers();
if (a <= 0 || a > max)printf("数据不合理,请重新输入!\n");
else break;
}
return a;
}
int selection(void a(), int *data) {
while (1) {
a();
int b = choose();
if (b == 1) {
*data = 1;
break;
} else if (b == 2) {
*data = 2;
break;
} else if (b == 3)return 1;
else printf("请输入有效选择!\n");
}
return 0;
}
int BasicSelection(int *object, int *order) {
while (1) {
int a = selection(SortOrder, order);
if (a == 1)return 1;
int b = selection(object_print, object);
if (b != 1)break;
}
return 0;
}
int sequence(chardata *a, int flag, int num, int way) {
int object = 1, order = 1;
if (flag == 1 && BasicSelection(&object, &order))return 1;
chardataHandle(&a, object, order, num);
int c = reasonableJudgment(num);
if (way == 1)printf("顺序第%d个字符是%c。\n", c, a[c - 1].data);
else printf("逆序第%d个字符是%c。\n", c, a[num - c].data);
return 0;
}
void charQuery_print() {
printf("请选择查询顺序:\n");
printf("%*sA.顺序(默认选择)\n", 14, " ");
printf("%*sB.顺序\n", 14, " ");
printf("%*sC.逆序(默认选择)\n", 14, " ");
printf("%*sD.逆序\n", 14, " ");
printf("%*sE.返回\n", 14, " ");
}
int charQuery(chardata *a, int num) {
while (1) {
charQuery_print();
int b = choose();
if (b == 1) {
if (!sequence(a, 0, num, 1))break;
} else if (b == 2) {
if (!sequence(a, 1, num, 1))break;
} else if (b == 3) {
if (!sequence(a, 0, num, 2))break;
} else if (b == 4) {
if (!sequence(a, 1, num, 2))break;
} else if (b == 5)return 1;
else printf("请输入有效选择!\n");
}
return 0;
}
void intervalQuery_print() {
printf("请选择查询对象:\n");
printf("%*sA.字符频率区间\n", 14, " ");
printf("%*sB.字符ASCII值区间(默认选择)\n", 14, " ");
printf("%*sC.返回\n", 14, " ");
}
int *findinterval(int *returnsize, chardata *a, int num, int frist, int last, int flag) {
int *b = (int*)malloc(num * sizeof(int));
*returnsize = 0;
for (int i = 0; i < num; i++) {
if (flag == 1 && a[i].num <= last && a[i].num >= frist)b[(*returnsize)++] = i;
if (flag == 2 && a[i].data <= last && a[i].data >= frist)b[(*returnsize)++] = i;
}
return b;
}
int interval(chardata *a, int num, int b) {
int frist = 0, last = 0;
while (1) {
printf("请输入区间起始位置:");
frist = enterNumbers();
if (frist > 0 && frist < num)break;
else printf("数据不合理,请重新输入!\n");
}
while (1) {
printf("请输入区间末尾位置:");
last = enterNumbers();
if (((b == 1 && last <= a[0].num) || (b == 2 && last <= 256)) && last > frist)break;
else printf("数据不合理,请重新输入!\n");
}
int size = 0;
int *c = findinterval(&size, a, num, frist, last, b);
if (size == 0)printf("该区间无符合值!\n");
else {
if (b == 1)printf("字符频率从%d到%d有:\n", frist, last);
else printf("字符ASCII值从%d到%d有:\n", frist, last);
for (int i = 0; i < size; i++) {
printf("%*s", 16, " ");
printf("%c %d\n", a[c[i]].data, a[c[i]].num);
}
printf("\n");
}
free(c);
return 0;
}
int intervalQuery(chardata *a, int num) {
qsort(a, num, sizeof(chardata), compare3);
while (1) {
intervalQuery_print();
int b = choose();
if (b > 0 && b < 3) {
if (!interval(a, num, b))break;
} else if (b == 3)return 1;
else printf("请输入有效选择!\n");
}
return 0;
}
void inputprint(chardata *a, int frist, int last, int num) {
for (int i = frist; i < last && i < num; i++) {
printf("%*s", 10, " ");
if (a[i].data != '\n')printf("%c%8d\n", a[i].data, a[i].num);
else printf("\\n%7d\n", a[i].num);
}
}
void pagprint(chardata *a, int pag, int num, int pagnum) {
int count1 = (pag - 1) * pagnum;
inputprint(a, count1, count1 + pagnum, num);
if (pag != 1)printf("上一页");
else printf("%*s", 5, " ");
printf("%*s", 17, " ");
if (pag * pagnum < num)printf("下一页");
printf("\n");
}
void pagQueryprintremind() {
printf("%*s输入提醒:\n", 18, " ");
printf("A.上一页");
printf("%*sB.下一页", 8, " ");
printf("%*sC.返回\n", 8, " ");
}
int pagQueryprint(int num) {
int a = 0;
while (1) {
printf("请输入每页展示数量:");
a = enterNumbers();
if (a <= num && a > 0)break;
else printf("数据不合理,请重新输入!\n");
}
pagQueryprintremind();
return a;
}
int pagQuery(chardata *a, int num) {
int b = pagQueryprint(num);
int d = 1;
pagprint(a, 1, num, b);
while (1) {
int c = choose(), flag = 0;
if (c == 1 && d - 1 >= 1)d--;
else if (c == 2 && num - d * b > 0)d++;
else if (c == 3)return 0;
else flag = 1;
if (!flag)pagprint(a, d, num, b);
else {
if (num - d * b <= 0 && c == 2)printf("已经到最后一页了!\n");
else if (d == 1 && c == 1)printf("已经到第一页了!\n");
else {
printf("请输入有效选择!\n");
pagQueryprintremind();
}
}
}
return 0;
}
int allQuery(chardata *a, int num) {
int object = 1, order = 1;
if (BasicSelection(&object, &order))return 1;
chardataHandle(&a, object, order, num);
inputprint(a, 0, num, num);
return 0;
}
void statistics_print() {
printf("请选择查询方式:\n");
printf("%*sA.单字符查询\n", 14, " ");
printf("%*sB.区间查询\n", 14, " ");
printf("%*sC.分页查询\n", 14, " ");
printf("%*sD.查询全部\n", 14, " ");
printf("%*sE.返回\n", 14, " ");
}
int statistics_main() {
char *a = name();
long long int num = 0;
chardata *b = statisticalTxt(a, &num);
if (b == NULL)return -1;
while (1) {
statistics_print();
int c = choose();
if (c == 1)charQuery(b, num);
else if (c == 2)intervalQuery(b, num);
else if (c == 3)pagQuery(b, num);
else if (c == 4)allQuery(b, num);
else if (c == 5)return 1;
else printf("请输入有效选择!\n");
}
free(a);
return 0;
}
int main() {
while (1) {
print_main();
int a = choose();
if (a != -1 && a != 4)printf("请输入文件名或文件路径:");
if (a == 1) {
if (!compress_main())printf("成功!\n");
else printf("失败!\n");
} else if (a == 2) {
if (!decode())printf("成功!\n");
else printf("失败!\n");
} else if (a == 3) {
if (statistics_main() != -1)printf("成功!\n");
else printf("失败!\n");
} else if (a == 4)break;
else printf("请输入有效选择!\n");
}
return 0;
}
注意:
1.该程序对非英文文本文件的解压存在解压失败的可能性,但大部分时候不会出现解压失败的情况。
2.对于输入,不支持输入非英文字符!
3.C语言版对错误处理不如EasyX版完善。