供参考:
有一些语法错误和逻辑问题
#include <stdio.h>
int main()
{
unsigned int a = 12;
int k, i = 0, j;
int num[50];
while (a != 0) {
k = a % 2; // 取模应该是 %
a = a / 2;
num[i++] = k; // 语句应该是这样的
}
for (j = i - 1; j >= 0; j--) {
printf("%d", num[j]);
}
return 0; // 应该放在 main 函数的最后
}
如果以上回答对您有所帮助,点击一下采纳该答案~谢谢
我们已经对整体的逻辑实现有了一个了解,现在就来看看具体的代码吧:
我们想要做到功能分模块,也就是我可以自主选择是压缩还是解压缩,并且查看情况,那么我们就把业务逻辑分离:
那么我们首先看看最简单的头文件huffman.h书写了什么东西吧!
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include<time.h>
#include<Windows.h>
struct HuffmanNode
{
int letter; //保存字符的映射
long count; //文件中该字符出现的次数
long parent, lchild, rchild; //构建二叉树所需的数据
char bits[256]; //对应的哈夫曼编码
};
struct HuffmanNode TreeNode[512], tmp, temp; //节点树,TreeNode.count用来记录数据出现的次数
//函数compress(),读取文件内容并加以压缩,将压缩内容写入另一个文档
int compress(const char* filename, const char* outputfile);
//函数:uncompress(),作用:解压缩文件,并将解压后的内容写入新文件
int uncompress(const char* filename, const char* outputfile);
头文件主要就写了一些定义,并包含了其他可能需要的头文件。
现在来看看test.c文件
为了我们更好的互动,在测试文件中书写一个菜单,供选择,那么这个代码很简单:
#include"huffman.h"//注意头文件的包含
void menu()
{
printf("\n1,压缩文件\n");
printf("2,解压缩文件\n");
printf("3,读取解压缩文件\n");
printf("4,查看哈夫曼编码\n");
printf("输入'q'退出程序\n");
printf("请选择需要的操作:\n");
}
至于功能的实现,我们自然还是选择swtich语句,这里我们就需要考虑可能要写的功能了,比如,压缩文件,我们书写一个compress()
函数,解压缩文件,我们书写一个uncompress()
函数,读取文件的话,其实不需要再写函数,可以直接在uncompree()函数里实现解压缩文件的读取,而查看哈夫曼代码,我们既可以在编写哈夫曼树的时候去书写,也可以在解压缩的时候书写。
所以,简单的讲,我们只需要书写两个模块,就可以实现我们想要的功能,那么我们先看看逻辑主函数里都写了什么吧!
当然,这里的主函数会在尾记的时候详细的说一遍,这里可以选择不去理解。
void main()
{
clock_t begin, end;
double cost;
FILE* fp;
char ch, temparray[30];
int ret1, ret2;
int choice, count = 0, n;
long f;
memset(&TreeNode, 0, sizeof(TreeNode));
memset(&tmp, 0, sizeof(tmp));
menu();
while (scanf("%d", &choice) == 1)
{
system("cls");
switch (choice)
{
case 1:
ret1 = compress("data.txt", "data.zip.txt");
menu();
break;
case 2:
//开始记录
begin = clock();
ret2 = uncompress("data.zip.txt", "data.unzip.txt");
//结束记录
end = clock();
cost = (double)(end - begin) / CLOCKS_PER_SEC;
printf("解压缩耗时: %lf secs\n", cost);
printf("压缩比率是%.3lf%%\n", ((double)ret1 / ret2) * 100);
menu();
break;
case 3:
printf("读取解压后的文件:\n");
if ((fp = fopen("data.unzip.txt", "rt")) == NULL) {
printf("读取失败!\n");
exit(1);
}
ch = fgetc(fp);
while (ch != EOF) {
putchar(ch);
ch = fgetc(fp);
}
fclose(fp);
menu();
break;
case 4:
if ((fp = fopen("data.zip.txt", "rb")) == NULL)
{
printf("读取失败!\n");
exit(1);
}
fseek(fp, 4, SEEK_SET);
fread(&f, sizeof(long), 1, fp);
fseek(fp, f, SEEK_SET);
fread(&n, sizeof(long), 1, fp);//读取字符种类总数
for (int i = 0; i < n; i++)
{
printf("字符:%-5c频数:%-6ld哈夫曼编码:%-20s", TreeNode[i].letter, TreeNode[i].count, TreeNode[i].bits);
count++;
if (count % 4 == 0)
printf("\n");
}
menu();
break;
case 6:
printf("欢迎再次使用!\n");
default:
break;
}
}
}
我们每次实现一个功能,再去选择另一个功能,就清理一下屏幕,所以这里书写了一个system("cls")
,以便屏幕看着整洁一点。当然,可以根据个人的需要去更改。
由于我们希望计算压缩比率,那么我们书写模块的时候,还需要注意需要返回字节数。也就是书写一个有返回值的函数。
现在要看懂这些代码还是不行的,因为这里的功能的选择依赖于书写的模块的内容。所以我们还得继续看看模块都写了什么,才能理解这个main()函数的含义(并且在尾记里还会再介绍的,保证让每个人能有所收获)。放心,笔者会一一解释所有的可能的难点。
#include <stdio.h>
#include <stdlib.h>
int main() {
int num;
printf("请输入一个十进制数:");
scanf("%d", &num);
// 判断输入是否非负
if (num < 0) {
printf("输入不合法!\n");
exit(1);
}
int arr[32], i = 0;
// 将十进制数转换成二进制数存储到数组中
while (num > 0) {
arr[i] = num % 2;
num /= 2;
i++;
}
// 反转数组,使得二进制数顺序正确
int len = i;
for (int j = 0; j < len / 2; j++) {
int temp = arr[j];
arr[j] = arr[len - j - 1];
arr[len - j - 1] = temp;
}
// 输出二进制数
printf("二进制数为:");
for (int j = 0; j < len; j++) {
printf("%d", arr[j]);
}
printf("\n");
return 0;
}