题解 P1953【易语言】
WanderingTrader · · 题解
社区里都说是大模拟,不过自己感觉还好,我自己写的就1.28k。写这题时我正陷入某杀的泥潭中,在好友的建议下决定先把这题切了涨了点信心。结果先A了某杀才A了这题
题目分析
操作流程:
-
读入一个字符串
IN。如果IN是文件名而不是0或1(直接看IN[0]即可),读入一个字符串ANS,为目标文件名的格式。 -
读入两个字符串
in,out,为格式。剩下的全部读进垃圾内存,但注意要记录文件名的数量n。令整数st为文件的起始编号 -
如果
IN是文件名的话,将in和out全部改成IN,从其中提取数字,处理出st,然后将out中的后缀改为ANS。 -
如果
IN不是文件名,直接将st设为IN代表的数字。 -
输出
代码
首先有一些功能函数:
del(s,u):将字符串s的第u位删除
void del(char* s,int u){for(int i=u;s[i];++i) s[i]=s[i+1];}
精准覆盖
find(s,l,r):在字符串s中找到第一个介于[l,r]之间的字符,没找到返回-1。如果找单个字符c可以find(s,c,c)。
int find(char* s,char l,char r)
{
for(int i=0,sz=strlen(s);i<sz;++i)
if(s[i]>=l&&s[i]<=r) return i;
return -1;
}
output(s,n):将代表文件名的字符串s中的编号修改为n,并输出。
void output(char* s,int n)
{
int p=find(s,'0','9');
while(isdigit(s[p+1])) del(s,p+1);
for(int i=0;i<p;++i) putchar(s[i]);
printf("%d",n);
for(int i=p+1,sz=strlen(s);i<sz;++i) putchar(s[i]);
}
于是代码就很简单了。
根据上面的步骤,1&2:
scanf("%s",IN);
if(IN[0]!='1'&&IN[0]!='0') scanf("%s",ANS);
scanf("%s%s",in,out);
while(~scanf("%s%s",tmp,tmp)) ++n;
3:
void solve()
{
memcpy(in,IN,sizeof(IN));
memcpy(out,IN,sizeof(IN));
int p1,p2=find(out,'0','9'),x=out[p2]-'0';
while(isdigit(out[p2+1])){x=x*10+out[p2+1]-48;del(out,p2+1);}//计算st 留下p2作为数字标识符
p1=find(out,'.','.');//找到分隔点
for(int i=p1+1,sz=strlen(out);i<sz;++i) out[i]=0;//先清空
for(int i=0,sz=strlen(ANS);i<sz;++i) out[i+1+p1]=ANS[i];//再拷贝
if(p2>p1) out[strlen(out)]='0';//数字在扩展名 补上已被清除的数字标识符
st=x;
}
//in main()
if(IN[0]!='1'&&IN[0]!='0') solve();
4:
else st=IN[0]-'0';
5:
void output(char* s,int n)
{
int p=find(s,'0','9');//找到数字标识符
while(isdigit(s[p+1])) del(s,p+1);//删除多余数字 留p标识
for(int i=0;i<p;++i) putchar(s[i]);
printf("%d",n);
for(int i=p+1,sz=strlen(s);i<sz;++i) putchar(s[i]);
}
// in main()
for(int i=0;i<n;++i)
{
//输出两个文件名 别忘了编号+st
output(in,i+st);
putchar(' ');
output(out,i+st);
puts("");
}
全部代码就不放了。
后记:此文写于切掉某棋后不久。感觉此题相比某杀和某棋这种大型模拟,或是某复杂度这种中型模拟,真是小巫见大巫了。只能算是和龙虎斗一个级别的小型模拟。(毕竟我这std才49行)