C语言程序设计基础--RLE压缩解压算法

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号同邮箱

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怡人蝶梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值