先说一下算法:
1、首先利用getchar()读取字符,字符可能包含空,设置在遇到换行符结束,这里会遇到一个问题,第一组输入完毕后结尾又一个回车会出现在下一组字符的第一个,对此可以设定first变量,第一组计算完毕后first=0,如果first=1再做后面的工作,首行的回车使得字符读取函数提前结束了。
下一组循环first=1,读取从第一个字母开始,去掉了上一组输入的影响。
这里还要注意存储字母到二维数组的算法,令二维数组列表示数据长度,行表示大小,每列存储2^n-1个数据,n从1开始向右递增。这是二进制的进位特性决定的
2、利用scanf读取命令序列,命令序列是多行的,但是不存在空,所以可以使用scanf,读取序列,拼接序列,将每一个独立的行整合到一起构成完整序列。
3、二进制转化十进制。
4、解码过程:解码过程需要设置解码长度和读取头,例如00101000序列,第一次的解码长度设置为3,读取头为0,提取出001转二进制为1,更新解码长度1,读取头为2,读取长度为1的的下一个0,计算0的长度为1,二进制对应0,将二维字符数组的对应字符存在一维数组中(这是因为命令段的更新,比如001,01,000分三行输入,直接输出只会重复输出,因为拼接过程如下:001,00101,00101000,通过不断覆盖一维数组得出最终结果),更新读写头为4,比较1是11111的子串(strstr实现),为什么用if(strstr)来说是子串而不是if(!strstr)说不是子串,可能因为NULL的逻辑反未知吧。1是子串,小结结束,通过读取后三位判断解码长度,更新读写头为7,发现000和000相等,结束该组输入并执行输出。(中间还有很多长度的问题和是否需要继续输入的判断,详见代码)。
问题:
1、拼接的问题,重复使用拼接加大了无效计算次数,比如上例拼接结果:001,00101,00101000,第一次读写的过程还需要在下一次再做一遍,一次类推,比如第一次需要做1次,第二次需要做3次,第三次需要做4次,其实完整序列只需要做4次就可以了,但是不断拼接的过程多了1+3=4次,这是非常可怕的。这是因为逻辑上输入终点无法在输入过程中被判断,如果不进行解码是无法知道什么时候输入结束,我不能张口说这是三行输入没有第四行,不经过解码是说不清的,所以每次输入都要配一个解码过程,重复计算的代价就很大了。
2、编写过程遇到的问题很多,不过一一改过来了,比如void和int函数区别,解码之前是想写void改一个全局变量来判断是否需要继续输入,后来发现void在运行过程改了它之后,在后续的顺序结构会被改回来,换成int型就是因为在返回数值后,剩下的顺序结构不会再执行了。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <iostream>
#include <math.h>
#define maxn 1000
char a1[maxn];//存储字母的
char a2[maxn];//存储数字的
char a3[maxn];//接受数字的
char a4[maxn];//存储准备转化二进制的序列
char a5[100];//全一比较串
char a6[maxn][maxn];//横轴存长度,纵轴存大小
int first=1;
//int o=1;//输入停止标号
using namespace std;
int change(char a[],int n)//二进制转十进制
{
int s=0;int t=1;
for(int i=n-1;i>=0;i--)
{
s=s+t*(a[i]-'0');
t=2*t;
}
return s;
}
void input_alpha()
{
int k=1;
for(int j=0;;j++)
{ int d=1;
for(int i=0;i<int(pow(2,k))-1;i++)
{ //printf("n次方-1等于%d\n",int(pow(2,k))-1);
a6[i][j]=getchar();
if(a6[i][j]=='\n'&&i==0&&j==0) {first=0;}
if(a6[i][j]=='\n') {d=0;break;}
}
k++;
//printf("Yes\n");
if(!d) {break;}
}
}
int explain()
{ //printf("Yes\n");
int dd=0;
memset(a4,'\0',sizeof(a4));//初始化a4串
memset(a5,'1',sizeof(a5));//初始化a5串为全1串
int n=3;//写入多少位到a4串做二进制转换
int t=0;//确定开始位置
//printf("a2长=%d\n",int(strlen(a2)));
while(t<strlen(a2))
{ if(strlen(a2)>=3)
{ n=3;int k=0;int i=0;
if(t+n>strlen(a2)) break;
for(i=t;i<t+n;i++)
{
a4[k]=a2[i];k++;
}
t=i-1;
if(!strcmp(a4,"000"))//如果a4串和000相等停止输入
{return 0;}
else
//最早的三位提取准备转换为十进制
{n=change(a4,n);}//printf("n=%d\n",n);}
if(strlen(a2)>=t+n+1)
{
while(t<strlen(a2))
{ int j=0;memset(a4,'\0',sizeof(a4));
for(int i=t+1;i<=t+n;i++)
{a4[j]=a2[i];j++;}
t=t+n;
if(strstr(a5,a4)) //如果a4是1111子串
{t=t+1;break;}
else
{
int p=change(a4,n);
int pp=int(strlen(a4))-1;
//printf("%c",a6[p][pp]);//输出字符
a1[dd]=a6[p][pp];dd++;
}
}
}
else break;
}
else {return 1;break;}
}
return 1;
}
void input_digit()
{
while(cin>>a3)
{
strcat(a2,a3);
//printf("%s\n",a2);
if(!explain()) break;
}
}
int main()
{
while(1)
{ memset(a1,'\0',sizeof(a1));
memset(a6,'\0',sizeof(a6));
memset(a2,'\0',sizeof(a2));
memset(a3,'\0',sizeof(a3));
memset(a4,'\0',sizeof(a4));
memset(a5,'\0',sizeof(a5));
input_alpha();//输入字母序列;
if(first)
{
input_digit();//输入命令序列;
printf("%s\n",a1);
}
first=1;
}
return 0;
}