题解 P3982 【龙盘雪峰信息解析器】
写了一篇没人写过的题解
其实这道题说简单,是很简单
但是难就难在它Error的判断和如何操作以0开头的单元
还有一个大家普遍被难的就是,不能操作到一半,输出输一半
哎,发现不对了,赶紧输出Error,这样输出就会变得很奇怪
所以最好像本解的put一样,先存进一个字符串,最后输出
下面我们来看看解析(纯模拟)
#include<iostream>
using namespace std;
string s,put="",nm;int pl=0,c,a,b;
string del(string c){for(int i=0;i<8;i++)c.erase(0,1);return c;}
//上面这个地方是每8位操作完毕后清除一次
//个人比较习惯操作字符串时都是在首位操作
int main()
{
cin>>s;
if(s.size()%8){cout<<"Error";return 0;}
//这个地方判断,因为它每8位一个单元
//所以一定是整数个单元。(易判断)
while(s.size())
{
if((s[0]!='0'&&s[0]!='1')||(s[1]!='0'&&s[1]!='1')||(s[2]!='0'&&s[2]!='1')||(s[3]!='0'&&s[3]!='1')||(s[4]!='0'&&s[4]!='1')||(s[5]!='0'&&s[5]!='1')||(s[6]!='0'&&s[6]!='1')||(s[7]!='0'&&s[7]!='1')){cout<<"Error";return 0;}
//这个地方写了这么大一长串,啥意思呢
//其实就是判断,因为它是一个二进制加密码
//所以每一位都必须是0or1(还不如开头直接全判)
else if(s[0]=='1'&&s[1]=='1'&&s[2]=='1'){if(pl){cout<<"Error";return 0;}s=del(s);put+=" ";continue;}
//这个地方的话是加空格
//但要注意,如果前一个单元是请求加法单元
//那么这个单元是空格,就错误了,所以应该判错
else if(s[0]=='1'&&s[1]=='0'&&s[2]=='1')
{
if(pl){cout<<"Error";return 0;}
//跟前一注释一样
int d=(s[7]-48)*1+(s[6]-48)*2+(s[5]-48)*4+(s[4]-48)*8+(s[3]-48)*16;
//这里算这个字母是什么
if(d>25){cout<<"Error";return 0;}
//防止超过
put+=(char)(65+d);
//注意一下,如样例,10100000代表A
//那么可以推出公式65+00000=ascii(65)=A
}
else if(s[0]=='0')
{
a=((s[7]-48)*1+(s[6]-48)*2+(s[5]-48)*4+(s[4]-48)*8+(s[3]-48)*16+(s[2]-48)*32+(s[1]-48)*64)/2;
if(!pl)//还没有加数
{
b=a,pl=1;//交换加数和被加数
}
else if(pl)//有加数
{
c=a+b;a=b=pl=0;nm="";
if(!c)nm="0";
else while(c){nm=(char)(c%10+48)+nm,c/=10;}
//这里,c有可能=0或高于一位数
//c=0在前一句,而后面是处理多位数
put+=nm;
//加到输出中
}
}
else{cout<<"Error";return 0;}
//如果这个单元不符合任意规则则出错
s=del(s);
//删除前八
}
if(pl)cout<<"Error";//最后单元为加数(无被加数)
else cout<<put;
}