题目:
考虑下面的01串序列:
0,00,01,10,000,001,010,011,100,101110,0000,0001,...,1101,1110,00000,...
首先是长度为1的串,然后是长度为2的串,依此类推。如果看成二进制,相同长度的后一个串等于前一个串加1,。注意上述序列中不存在全为1的串。
你的任务是编写一个解码程序。首先输入一个编码头(例如 AB#TANCnrtXc),则上述序列的每个串依次对应编码头的每个字符。例如,0对应A,00对应B,01对应#,...,110对应X,0000对应c。接下来是编码文本(可能由多行文本组成,你应当把他拼成一个长长的01串)。编码文本由多个小节组成,每个小节的前3个数字代表每个编码的长度(用二进制表示,例如010代表长度为2),然后是各个字符的编码,以全1结束(例如,编码长度为2的小节以11结束)。编码文本以编码长度为000的小节结束。
例如,编码头为$#**\,编码文本为0100000101101100011100101000,应这样编码:010(编码长度为2)00(#)10(*)11(小节结束)011(编码长度为3)000(\)111(小节结束)001(编码长度为1)0($)1(小节结束)000(编码结束)。
分析:
还记得二进制码?有了二进制,就不必以字符串的形式保存这一大串编码了,只需把编码理解成二进制,用(len,value)这个二元组来表示一个编码,其中len是编码长度,value是编码对应的十进制值。如果用codes[len][value]保存这个编码所对应的字符,则主程序看上去应该是这个样子的。
回答:
#include<stdio.h>
#include<string.h> //使用memset
int readchar()
{
...
}
int readint()
{
...
}
int main()
{
while(readcodes())
{
//无法读取更多的编码头时退出
for(,,)
{
int len = readint(3);
if(len == 0) break;
//printf(“len=%d\n”,len);
for(;;)
{
int v = readint(len);
//printf("v=%d\n",v);
if(v == (1<<len) - 1) break;
putchar(code[len][v]);
}
}
putchar('\n');
}
return 0;
}
int readchar()
{
for(;;)
{
int ch = getchar();
if(ch != '\n' && ch != '\r') return ch; //一直读到非换行符为止
}
}
int readint()
{
int v=0;
while(c--)
v=v*2+readchar() - '0';
return v;
}