做题细节:
1、咋么读入换行?
一开始想到'\0'和EOF两个截止符,但前者效果不好,后来上网查了查两个的区别,EOF用于文件读取,而'\0'只用于字符串结尾,所以正确读取方式为scanf+EOF。另外,这种方法还可以帮助我们得知字符串长度n:
while(scanf("%c",&s[++n])!=EOF);
2、如何简化代码?
我们可以在内层循环里,通过讨论不同情况为i加速。比如想要判断 /* ,就必须满足s[i]=='/'&&s[i+1]=='*',所以在这种判断下加速了i+1的进程,直接在循环体内部让i++即可。
3、关于思考不周的问题(调了我一个点QAQ……)
/**/部分没考虑周到。一开始是用队列存储,判断条件是s[i]=='*'&&s[i-1]=='/'就视为匹配情况退出循环,此时漏掉了一种毒瘤情况:/*/。所以说审题的重要性啊,题目中其实已经给过这种情况了。
4、“探查兵”法
后来发现用队列其实是多余的,可以通过设置i在输出字符前先探探路,若符合则使j从一开始的位置往后输出,像是先派出了探查兵。分析可以发现,这种方法可以使用于这种前后有标志性开始结束标志的处理要求的题,较之前的内层循环有不易错判循环状态的好处。
总结完毕,上代码:
#include<bits/stdc++.h>
#include<stdio.h>
using namespace std;
#define N 100000
char str[N];
int main() {
int a=0,k=0,n,f=0;
while(scanf("%c",&str[++n])!=EOF);
// str[n]='&';
n--;
for(int i=1; i<=n; i++) {
if(str[i]=='"'&&str[i-1]!='\\') {
cout<<str[i];
i++;
while(1) {
cout<<str[i];
if(i>n||str[i]=='"'&&str[i-1]!='\\')break;
i++;
}
} else if(str[i]=='/'&&str[i+1]=='*') {
int j=i;
i+=3;
while(1) {
if(i>n||(str[i]=='/'&&str[i-1]=='*'))break;
i++;
}
//cout<<i<<endl;
if(i>n) while(j<=n) cout<<str[j++];
} else cout<<str[i];
}
}