例题4-4 信息解码 UVa213

题目
对于下面这个字符串:
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);你...懂我意思吧?

具体请移步http://t.csdn.cn/MQ10X

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值