题目
对于下面这个字符串:
0,00,01,10,000,001,010,011…….
首先是长度为1的串,然后是长度为2的串,以此类推。不存在全为1的串。
你的任务是编写一个程序。首先输入一个代码头(例如AB#TANCnrtXc),则上述序列的每个串依次对应编码头的每个字符。例如,0对应A,00对应B,01对应#…,0000对应c。接下来是编码文本(可能由多行组成,你应当把他们拼成一个长长的01串)。编码文本由多个小节组成,每个小节的前3个数字代表小节中每个编码的长度,用二进制表示,然后是个字符的编码,以全1结束。编码文本以000结束。
分析
读取
读取代码头
读取编码文本
转换
二进制转换
存储
数组存储 code[len编码长度][所对应的十进制]
设计函数
设计一个读取代码头的函数
设计一个将二进制转化为十进制的函数
设计一个能读取编码文本(被分割成多行)的函数
这道题在做的时候,第一遍读题确实是没看懂题目(本人英文水平不太行),所以我就在看书上的大致题意才了解了题目(因为不小心偷看了一点书上的分析,所以书上的函数我搬过来两个用了),形成了我下面的初步代码(注意,以下代码有bug):
#include <bits/stdc++.h>
#include <string>
string s;
string ss;
char p[8][1<<8];
char readchar()
{
for(;;)
{
char ch=getchar();
if(ch!='\n'&&ch!='\r')
return ch;
}
}
int readint(int c)
{
int v=0;
int x=c-1;
while(c--)
{ v+=(readchar()-'0')*pow(2,x--); }
return v;
}
int main()
{
while(getline(cin,s))
{
p[8][1>>8]={'0'};
int len=1;
int i=0;
int flag=1;
while(len)
{
for(int j=0;j<=pow(2,len)-2;j++)
{
if(i<s.size())
{
p[len][j]=s[i];
i++;
}
else if(i==s.size())
{
flag=0;
break;
}
}
if(!flag)
break;
len++;
}
while(1)
{
int k=readint(3);
if(k==0)
break;
while(1)
{
int m=readint(k);
if(m==(i<<k)-1)
break;
cout<<p[k][m];
}
}
cout<<endl;
p[7][1>>8]={'0'};
}
return 0;
}
后面的这个while循环调了很多次,之前我是想直接用while(readint(3)),但是进去之后还是需要用到readint()函数,一个函数用两次不就是相当于读取了两次字符吗?这和我的思路有背,所以我就用了while(1)结构,但是我的问题出在了读取代码头的位置上,也就是第一个while循环的位置,getline有两种用法,一种是cin.getline(char *,int)(用于字符数组的情况),第二种是getline(cin,str)(用于字符串的形式),但是第二种(也就是我在上面写的那种),这种情况在读取到换行符(也就是我们本意的字符串结束标志)的时候,会读取并丢弃掉换行符,也就意味着我们输入完编码头之后的结束标志失去了作用,这就对后面01字符串的输入造成了影响,就会导致bug,所以我搜寻大佬的代码,看到他们都是逐一读取字符并以换行符终止的方式来读取代码头的,这里要对getchar的用法很熟悉,注意getchar也会吸收换行符(但是编码头结束的最后一个换行符不能吸收),否则可能会出错。下面就是大佬的代码了:
#include <stdio.h>
#include <string.h>
char codes[8][1<<8];
int readchar(){
char ch;
while(1){
ch=getchar();
if(ch!='\r'&&ch!='\n')
return ch;
}
}
int readcodes(){
int len;
int i;
char ch;
memset(codes,0,sizeof(codes));
codes[1][0]=readchar();
for(len=2;len<=7;len++)
for(i=0;i<(1<<len)-1;i++){
ch=getchar();
if(ch==EOF)
return 0;
if(ch=='\n')
return 1;
codes[len][i]=ch;
}
return 1;
}
int readint(int c){
int v=0;
while(c--){
v=v*2+readchar()-'0';
}
return v;
}
int main(){
int len;
int i;
while(readcodes()){
while(1){
len=readint(3);
if(len==0)
break;
while(1){
i=readint(len);
if(i==(1<<len)-1)
break;
putchar(codes[len][i]);
}
}
putchar('\n');
}
return 0;
}
对了,还要说一下这个1<<8表示1*pow(2,8);你...懂我意思吧?