题目链接
题解模拟?
先说明一下不考虑printf
中输出的/
等情况,不要将输入理解为代码,而是理解为若干行字符串,去掉/**/
内部的内容和去掉//
所在行之后的内容。
我们分为三部分实现(我将按我的思考过程讲述):
一、我们最先能想到的就是判断注释部分是否开始。
注释分两种,一种是/**/
,另一种是//
。开始条件很明显,第一种遇到/*
开始,第二种遇到//
开始。当然这俩字符也不能输出。
若当前获取到的字符 c
为 /
,那么我们立即再获取下一个字符 cc
,
- 若
cc
是/
说明//
开始了,用标记two = 1
表示//
开始,continue
掉即可; - 若
cc
是*
说明/*
开始了,用标记one = 1
表示/*
开始,continue掉即可; - 若 不满足上面两种情况,即else,那么输出一下
c
和cc
。
否则(当前获取到的字符 c
不是 /
),那么正常输出 c
即可。
PS: 可能有人会有疑惑,一次获取两个,万一 c
和 cc
无法配成 /*
或 //
,但是 cc
和下一个字符说不定就配成了,那你现在把 cc
提前取出来并输出了,不会出错吗
答案是不会的,反证一下:因为如果要上述的错误,即c
和 cc
无法匹配,而 cc
和下一个字符匹配成功。因为 cc
和下一个字符匹配成功,那么就要保证 cc
是 /
才行。进入获取 cc
语句的前提是 c
为 /
,如果 cc
是 /
,那么c
和 cc
必然匹配成功啊,这不与 c
和 cc
无法匹配的条件相违背嘛。因此不用存在这方面的疑虑。
二、 注释部分
这部分比较好考虑,根据标记我们可以轻松判断出是否处于注释部分,处于注释部分什么也不用输出直接continue就行。
三、 判断注释是否结束
两种注释对应的结束条件分别是 */
和 '\n'
。
*/
的判断:先保证one == 1
说明处于第一种注释状态,再判断当前字符c
的前一个字符是否为星号(这时候我们就不能取c
的后一个字符判断是否匹配了,因为这时候多取一个字符是不满足上述PS部分证明的)。如果前一个字符为星号且c
为/
则结束注释,重置标记,continue
。'\n'
的判断:先保证two == 1
说明处于第二种注释状态,若当前字符c
是回车符,则输出回车符,重置标记,continue
即可。
三部分的思路都明白了,但实际上三段代码顺序应该为“三”、“二”、“一”。 判断结束在前,其次是注释部分continue
,最后才是判断开始。 这个你应该可以自己理解。
最后给个样例,这个对了应该就AC了(我觉得)
abscasc//daw/*dawdaw*/
/dawda*/
/*/abdwh
dawda
*/dawdaw
daw/*//a/b/c//*/dawd
/*//dawda
看高亮就知道哪些该输出哪些不该输出了。
#include
using namespace std;
char c;
int xing, two, one; // xing代表获取的当前字符c的前一个字符是否为星号 one代表 /**/ 注释 two代表 // 注释
int main()
{
while((c=getchar()) != EOF) {
// 判断注释结束
if(two && c=='\n') { two = 0; putchar(c); continue;} // 把回车输出一下
else if(one) {
if(xing && c=='/') { one = 0; xing = 0; continue;}
if(c=='*') xing = 1;
else xing = 0; // 每次获取的不是星号后都要修改
}
// 注释部分 continue
if(one || two) continue;
// 判断注释开始:若符合开始条件则进行标记,不符合就正常输出字符
if(c=='/') {
char cc = getchar();
if(cc == '/') {
two = 1;
continue;
} else if(cc == '*') {
one = 1;
continue;
} else {
putchar(c);
putchar(cc);
continue;
}
} else putchar(c);
}
return 0;
}