考虑下面的01串序列:
0, 00, 01, 10, 000, 001, 010, 011, 100, 101, 110, 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的小节结束。
这是遇到的第一个对我来说比较难的题,花了两三小时写出来的,而且有一点错误。getchar输入时,循环输入时回车键不易处理,添加一个判断语句控制忽略回车。因此加一个readchar函数。
最终代码是没问题的,感觉还可以再改进。
重点是readint函数,读取c个长度的二进制字符,返回出整型十进制数字。
redecodes读取给出的编码头
#include<stdio.h>
#include<iostream>
#include<String.h>
#define MAXN 81
using namespace std;
char code[8][1<<8] = {0};//code[len][value] len是长度,value是对应十进制的值
int readchar() {
for(;;)
{
int ch = getchar();
if(ch != '\n' && ch != '\r') return ch; //一直读到非换行符为止
}
}
int readint(int c) //读取 c位二进制字符
{
int v = 0;
while(c--)
{
v = v + (1<<c) * (readchar() - '0');
}
return v;
}
int readcodes() // 读取编码头 保存到code[][]
{
char head[MAXN];
int i = 1, count = 0;
scanf("%s", head);
while(i <= strlen(head))
{
int j = 0;
while(i <= strlen(head) && j < (1<<i)-1) // j< i的平方-1
{
code[i][j++] = head[count++];
}
i++;
}
return 1;
}
int main()
{
while(readcodes()) // 循环读取编码头
{
printcodes();
while(1)
{
int len = readint(3); // 读取前三位 转成二进制表示长度
if(len == 0) break;
while(1)
{
int v = readint(len); // v代表每次读取len位的值
if(v == (1 << len)-1) break; // (1<<len)-1表示1左移len位后减一得到全一。或者可以理解为1*2的len次方减一
putchar(code[len][v]); // 打印出 (len, v)的字母值
}
}
putchar('\n');
memset(code, 0, sizeof(code));
}
}