RLE压缩解压算法
涉及知识点:文件读写、位操作、内存管理、结构体定义、RLW算法、命令行参数
要求:
编写一个程序,可以在命令行输入参数,完成指定文件的压缩解压
命令行参数如下
rle file1 –c(-d) file2
第一个参数为可执行程序名称,第二个参数为原始文件名,第三个参数为压缩或解压缩选项,第四个参数为新文件名
#include <cstdio>
#include <cstdlib>
#define T 10000
#define M 128
int IsRepeat(const unsigned char *str, int number);
int GetRepeatNumber(const unsigned char *str, int number);
int GetNotRepeatNumber(const unsigned char *str, int number);
int Rle_encode(const unsigned char *str, int ori_num, unsigned char *stm, int cur_num);
int Rle_decode(const unsigned char *str, int ori_num, unsigned char *stm, int cur_num);
unsigned char ori_str[T];
unsigned char cur_stm[T];
int main(int argc, char ** argv)
{
//printf("%d\n", 10);
if (argc != 4) return -1;
//初始化
//printf("%d\n", 122);
FILE *fp ;
FILE *new_file;
//printf("%d\n", 222);
//打开文件
if ((fp = fopen(argv[1], "rb")) == nullptr)
{
fprintf(stderr, "Error in opening file %s", argv[1]);
exit(EXIT_FAILURE);
}
if ((new_file = fopen(argv[3], "wb")) == nullptr)
{
fprintf(stderr, "Error in opening file %s", argv[3]);
exit(EXIT_FAILURE);
}
//printf("%d\n", 11);
//读取数据
int i = 0;
while (fread(&ori_str[i], sizeof(unsigned char), 1, fp) == 1)
{
i++;
}
//rewind(fp);
/*
while (ori_str[i] != '\000')
{
i++;//?
}*/
//printf("%d\n", 12);
//压缩解压缩
//printf("%c %c", *argv[2], *(argv[2] + 1));
if (*(argv[2] + 1) == 'c')Rle_encode(ori_str, i, cur_stm, T);
else if (*(argv[2] + 1) == 'd') Rle_decode(ori_str, i, cur_stm, T);
else {
fprintf(stderr, "Error in cmdlet ");
}
//写入数据
//printf("%d\n", 13);
unsigned int j = 0;
while (cur_stm[j] != '\000')
{
fwrite(&cur_stm[j], sizeof(unsigned char), 1, new_file);
j++;
}
//关闭文件
if (fclose(fp) != 0 || fclose(new_file) != 0)
{
printf("Error in closing file %s or %s\n", argv[1], argv[3]);
}
//printf("%d\n", 14);
return 0;
}
//有重复是返回1
int IsRepeat(const unsigned char *str, int number)
{
//小于3认为没有重复
if (number < 3) return 0;
if (str[0] == str[1] && str[1] == str[2]) return 1;
return 0;
}
int GetRepeatNumber(const unsigned char *str, int number)
{
if (number < 3) return 0;
int j = 0;
while (str[0] == str[j++] && j <= number && j <= 127);
return --j;
}
int GetNotRepeatNumber(const unsigned char *str, int number)
{
if (number < 3) return number;
int k = 0;
while ((str[k + 1] != str[k + 2] || str[k] != str[k + 1]) && k < number - 2 && k <= 125) k++;
return k + 2;
}
int Rle_encode(const unsigned char *str, int ori_num, unsigned char *stm, int cur_num)
{
int ori_num_tmp = ori_num;
int enSize_str = 0;//原数据已参与编码长度
int enSize_stm = 0;//新数据长度
while (ori_num_tmp - enSize_str > 0)
{
//空间不足
if (cur_num - enSize_stm < 3)
return -1;
if (IsRepeat(&str[enSize_str], ori_num_tmp - enSize_str))
{
int count_repeat = GetRepeatNumber(&str[enSize_str], ori_num_tmp - enSize_str);
stm[enSize_stm++] = count_repeat;
stm[enSize_stm++] = str[enSize_str];
enSize_str += count_repeat;
}
else
{
int count_not_repeat = GetNotRepeatNumber(&str[enSize_str], ori_num_tmp - enSize_str);
stm[enSize_stm++] = count_not_repeat + M;
/*if (enSize_stm + count_not_repeat < cur_num)
return -1;*///?
while (count_not_repeat--)
{
stm[enSize_stm++] = str[enSize_str++];
}
}
}
return 0;
}
int Rle_decode(const unsigned char *str, int ori_num, unsigned char *stm, int cur_num)
{
int ori_num_tmp = ori_num;
int deSize_stm = 0;
int deSize_str = 0;
while (ori_num_tmp - deSize_str > 0)
{
//空间不足
if (cur_num - deSize_stm < 3)
return -1;
if (int(str[deSize_str]) > M)
{
int i = int(str[deSize_str]) - M;//不重复长度
while (i--)
{
stm[deSize_stm++] = str[++deSize_str];
}
deSize_str++;
}
else {
int k = int(str[deSize_str]);
while (k--) {
stm[deSize_stm++] = str[deSize_str + 1];
}
deSize_str += 2;
}
}
return 0;
}
/*scanf("%s", ori_str);
int i = 0;
while (ori_str[i++]);
i--;
Rle_encode(ori_str, i, cur_stm, T);
int k = 0;
while (cur_stm[k++]);
k--;
Rle_decode(cur_stm, k, ori_str, T);
int j = 10;
while (j--)
{
printf("%c", cur_stm[9 - j]);
}*/
ps:如有错误敬请指正,欢迎评论区交流或者发私信
邮箱1654407501@qq.com,QQ号同邮箱