审题
清楚编码文本是怎样生成的,自己研究!基本是能看懂的!
读一遍题目,不知道要干啥,看得懂怎么解密加密,不会写代码,具体写什么东西?
1.划重点:
2.解决重点:
①你要编写的是一个解码程序,这个解码程序是个什么样子的?
你不需要给出任何的输入语句,输入是测试数据时写好的,例如:
$#**\
0100000101101100011100101000
上解码工具,你的代码要做到对上面的数据进行解析:
##*\$
你编写代码时就想象屏幕上就有测试数据,你直接调用合适的读取函数读取就行!
②解决多行问题?
上面的那串$#**\字符是编码头;长长的01串就是编码文本,这个编码文本可能是多行,意思就是可以出现换行,即:
$#**\
01000001011
011000111
00101
000
当然这个换行是按照题目所规定的规律换行的,每到小节结束另一个小节开始可以换行,那么怎么解决读这些代码的时候可以处理换行了?
写一个函数readchar();
不断被读取代码,当遇到\n \t的时候,就跳过,继续往下读取,当读取到非换行符的时候即文件结束符EOF时,就跳出循环。
int readchar(){
int ch=getchar();
while(ch!='\n'&&ch!='\r') return ch;
/*
在Windows中:
'\r' 回车,回到当前行的行首,而不会换到下一行,如果接着输出的话,本行以前的内容会被逐一覆盖;
'\n' 换行,换到当前位置的下一行,而不会回到行首;
所以需要用到&&
*/
}
③每个小节的前3个数字代表小节中的编码长度?
意思是,每一个小节的前三个数字,例如010,转化成十进制是2,即以下的01串每2个长度保存了该小节中的一个字符信息,直到读到特殊意义的串就停止字符解析。
重点在于理解,这种你该解析的串有多少种长度类型了?前3个数字代表小节中的编码长度,很容易想到二进制,有多少种二进制组合,抛去题目说的000有特殊意义外,剩下有7个,即001、010、011、100、101、110、111,转换成十进制后,分别代表小节中长度为1、2、3、4、5、6、7的串代表一个字符!意思就是,这种该解析的串的范围在1-7个长度!
④怎样储存这些01串?
观察01串,0、00、01、000、001、010、011、100、101、110……
长为1的串:转成十进制0;
长为2的串:转成十进制0、1;
长为3的串:转成十进制0、1、2、3、4、5、6;
长为4的串:转成十进制0、1、2、3、4、5、6、7、8、9、10、11、12、13、14、15
……
仔细看这些标黄数字,怎样存储?且要维护顺序。
二维数组!这个二维数组就已经维护了顺序生成的01串编码头
int code[len][value]
为什么是整型?
1.你所对应的01串可换算成十进制的具体值
2.你的密码字符虽然是char类型,但注意一点,它并没有汉字,也就是说它只是一些普通的字符而已,都可以映射成相应的ASCII码,你存进int类型数组中时,便自动的跟你转换成了相应ASCII码,当你要输出时,只需要以%c的形式输出里面的相应ASCII码,便是对应码字符!
len代表该串长度,value代表串的对应十进制值
这个二位数组初始化空间多大?
②中已经详细的说了,01串只有7中长度类型,1-7,所以len=8(0-7);value代表串的对应十进制值,不难想到肯定要大于等于最大的二进制表达数,即当01串长度为7且全为1的时候最大,27,约定初始化空间稍大于数据规模。
int code[7][1<<8]
架构(伪代码解题思路)
1.读第一行的密码字符,一个一个读,并按照顺序存储到codes数组中;<<readcodes()>>
2.读接下来可能有多行的01编码密码串。
按照题目要求读:①首先读前三个串,通过函数转换成十进制数值len<<readint(3)>>;判断len是否是特殊意义的串000代表编码密码串结束!
② 其次去读指定len数值长度的01串,换成十进制数值value<<readint(len)>>,判断value是否是小节结束的特殊值,不是则利用,是则break去读下一小节,即又从①开始了!
③从codes数组找对应字符,即codes[len][value]!输出<<putchar(codes[len][value])>>
④循环①②③,直到碰壁①的条件!
int main(){
while( readcodes() ){
for( ; ; ){
int len=readint(3);
if(len==0) break;//编码密码串结束标志位000
for( ; ; ){
int value=readint(len);
if(value==(1<<len)-1) break;//每小节结束标志位,全1
putchar(codes[len][value]);
}
}
}
return 0;
}
大概解题思路缕完,可以先自己尝试着敲一遍代码,完善细节!
注意readcodes()函数中的细节
代码
#include<stdio.h>
#include<string.h>
int readcodes();//处理第一行要加密的字符串,改换成相应编码头存进数组
int readint(int);//将指定长度01串转换成整型
char readchar();//读串
int codes[8][1<<8];
int readint(int s){
int number=0;
while(s--) number=number*2+readchar()-'0';//进制转换
return number;
}
int readcodes(){
memset(codes,0,sizeof(codes)); //每次都需要初始化密码字符数组
codes[1][0]=readchar();//先存储第一个,之后的密码字符便可按照规律循环存储
int i,j;
for(i=2;i<=7;i++){
for(j=0;j<(1<<i)-1;j++){
int ch=getchar();
if(ch==EOF) return 0;//文件结束符
if(ch=='\n'||ch=='\r') return 1;//读到了空格或者转行,终止函数,不用存进密码字符数组中
codes[i][j]=ch;
}
}
return 1;
}
int readchar(){
int ch=getchar();
while(ch!='\n'&&ch!='\r') return ch;//用于针对密码文本多行的情况,如果时换行继续往下读再返回字符
}
int main(){
while( readcodes() ){
for( ; ; ){
int len=readint(3);
if(len==0) break;
for( ; ; ){
int value=readint(len);
if(value==(1<<len)-1) break;
putchar(codes[len][value]); //把存进去的相应ASCII码输出转换成字符
}
}
printf("\n");
}
return 0;
}