题目链接
题解模拟?
先说明一下不考虑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; }
