信息解码(ACM)刘汝佳

题目
考虑下面01串序列:
0,00,01,10,000,001,010,011,100,101,110,0000,0001,…,1101,1110,00000,…
首先是长度为1的串,然后是长度为2的串,依次类推。可以将此串看作二进制串。注意:上述序列不存在全为1的串。
编写一个解码程序。
首先输入一个编码头(eg:AB#TANCnrtXc),则上述序列的每个串依次对应编码头的每个字符。(eg:0对应A,00对应B,#对应01,T对应10,依次类推)
编码文本由多个小节组成,每个小节的前3个二进制数代表字符编码的长度(eg:010对应长度为2),然后是各字符编码,以全1结束(eg:编码长度为2,就以11结束)。编码文本以000的小节结束。

我先讲解一下位运算
"<<"左移运算,“>>”右移运算
eg:1<<8 即1✖2的8次幂
eg1>>8 即1➗2的8次幂
一个n位的二进制数,最大数为n个1
eg:8位的二进制数最大数为11111111(8个1)
将上述n位最大的二进制数,转换位十进制用位运算来计算
即(1<<n)-1
eg:111转换位十进制(1<<3)-1{2的3次幂减去1为7}

这道题的整体思路:
先用readcodes()读取编译头,并且存放到code[len][value]数组中,再读取编译文本,将编译文本用readint()方法转换为十进制数,在对应到code[len][value]中的值,并将其输出!其中的代码细节我都写在了注释里,以便大家详细阅读!

#include <iostream>
using namespace std;
int code[8][1<<8];//开一个code用于存放编译头
//code[len][value],len位二进制有多少位,eg:001即三位最大为8位,1<<8为左移的位运算(位运算写在代码块下边的讲解部分)


//readchar()防止输入数据中有换行符
int readchar()
{
    for(;;)
    {
         int ch=getchar();
        if(ch!='\n'&&ch!='\r')return ch;//只要不为换行符,就返回ch的ASCII码值
    }
}
//将c位的二进制数转换为十进制
int readint(int c)
{
    int v=0;
    while(c--)
    {
        v=v*2+readchar()-'0';//eg:110=(1*2+1)*2+0
    }
    return v;
}
 //读取编译头,将编译头中的字符,存放到code[len][value]中
 int readcodes()
 {
     memset(code,0,sizeof(code));//清空数组
     code[1][0]=readchar();//因为第一个二进制只有一位0,所以单独拿出来读取
     for(int len=2;len<=7;len++)
     {
         for(int i=0;i<(1<<len)-1;i++)//i小于len位二进制转十进制后的"最大数"
         {
             int ch=getchar();
             if(ch==EOF)return 0;//EOF表示读取结束
             if(ch=='\n'||ch=='r')return 1;//遇到换行,接着读取
             code[len][i]=ch;//将ch归位
         }
     }
     return 1;
 }
int main()
{
   while(readcodes())//读取预编译头
   {
       //printcodes()//可以把注释去掉方便调试
       for(;;)
       {
           int len=readint(3);//读取编译文本的前三位,即小节中的编码长度
           if(len==0)break;//当这段二进制小节有0位,直接break
           for(;;)
           {
               int v=readint(len);//往后读取len位二进制数,v存放所对应的十进制数
               if(v==(1<<len)-1)break;//当读到有len个1时,证明读取到这小节的末尾,直接break跳出循环
               putchar(code[len][v]);//不然输出有len位,十进制为v的char型字符
           }
       }
       putchar('\n');
   }
    return 0;
}

谢谢大家观看,多多点赞支持!

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值