《编程思维与实践》1052.删除注释
题目
思路
将所有可能的情况枚举出来:
1.在有效的块注释内: 有效是指块注释不在引号内,如
char *s=" \ * xxxxxxx *\ "
就不是一个有效的块注释,这种情况下跳过之后所有的内容,直到遇到*/后才重新判断情况;
2.在有效的行注释内: 同理,有效是指行注释不在引号内,如
char *s=" // xxxxxxx // "
就不是一个有效的行注释,这种情况下跳过该行的剩下内容(直接break);
3.其余情况直接输出内容,每行结束时如果不在块注释内需要输出回车.
关键在于如何判断是否有效,即判断是否在两个引号内:
如
"sdjksd\"\\d//fj/*kdhjk\"dsfjl*/dks"
中首尾两个引号中间的其余引号应该忽略,所以可以利用strchr来判断是否为最后一个引号,若不为最后一个引号则表示还在引号中.
注意的点:
如果在有效的块注释中,一直到末尾都没有遇到*/则余下的内容全部被注释.
代码
#include<stdio.h>
#include<string.h>
int main()
{
char s[1000];
int flag1=0,flag2=0; //flag1记录是否遇到/* flag2记录是否在" "内
while(gets(s)!=NULL)
{
for(int i=0;i<strlen(s);i++)
{
if(flag1==0) //不在块注释内
{
if(s[i]=='"') // 如果遇到//上一步已经则直接break
{
putchar(s[i]);
if(strchr(&s[i+1],'"')!=NULL)
{
flag2=1;
}
else //最后一个双引号
{
flag2=0;
}
}
else if(s[i]=='/'&&flag2==0) //不在引号内
{
if(s[i+1]=='/') // 遇到//直接跳过这一行
{
break;
}
else if(s[i+1]=='*') // 遇到/* i++循环再i++ 一共加2次
{
flag1=1;
i++;
}
else
{
putchar(s[i]);
}
}
else //其他情况直接输出
{
putchar(s[i]);
}
}
else if(s[i]=='*'&&s[i+1]=='/') // 在块注释内并且遇到*/ 同样i要加2次
{
i++;
flag1=0;
}
}
if(flag1==0)
{
printf("\n");
}
}
return 0;
}