一个比较常见的题。这个题应该是要比看上去的难不少。如果用正则,可能会好一些。
使用FSM解答。
核心思想是向后看一步。
对于每次读入的字符,实际上我们不能立即判断出它是否是注释,只有向后多看一个,来判断前面读到的这个字符是代码还是注释。
例如: te/st//comment
假设有个缓存,长度是2个字节,存储当前处理的字符和上一个字符。
第一次读到‘/’时,缓存中是“e/”,输出“e”.
读下一个,缓存中是“/s”,不匹配注释,“/”直接被输出
下一次读到‘/’时,缓存中是“t/”, 这时我们可以知道t不是注释中的一部分,直接输出。
下一步,缓存就为“//”,我们知道了这个和一个注释开始符匹配,剩下的就当做注释处理。
同样的,在判断注释结束时,我们依然要多向后看一部。
下面给出一个示意的有限状态自动机。用queue代表缓存,然后使用一个flag comments来标记是否是注释。
这里仅仅是一个示意图,表示了关键的一部分。实际还有很多缺失的细节。
1.注释有//和/* */两种,因此开始注释和结束注释的判断都不一样。
2.要考虑转义字符的问题。
3.处理结束后,要将缓存中剩余的2个char根据状态输出。
具体细节可以参考下面的代码。(未经完全测试)
-
#include <stdio.h>
-
#include <stdlib.h>
-
char* filter(const char* input){
-
if(input == NULL) return NULL;
-
-
int len = strlen(input) +1;
-
-
char* ret = (char*)malloc(len);
-
int index = 0;
-
int r = 0;
-
int comments = 0;
-
char cache[3];
-
cache[0] = '\0';
-
cache[1] = '\0';
-
cache[2] = '\0';
-
for(;r<len;r++){
-
cache[strlen(cache)] = input[r];
-
if(strlen(cache)!=2)
-
continue;
-
if(comments>0){
-
if(comments == 1 && cache[1] == '\n'){
-
cache[0] = '\0';
-
cache[1] = '\0';
-
comments = 0;
-
continue;
-
}
-
if(comments == 1 && cache[1] != '\n'){
-
cache[0] = cache[1];
-
cache[1] = '\0';
-
continue;
-
}
-
if(comments == 2 && cache[0] == '*'&& cache[1] == '/'){
-
cache[0] = '\0';
-
cache[1] = '\0';
-
comments = 0;
-
continue;
-
}
-
if(comments == 2 && !(cache[0] == '*'&& cache[1] == '/')){
-
cache[0] = cache[1];
-
cache[1] = '\0';
-
continue;
-
}
-
-
}
-
else{
-
//escape char
-
if(cache[0] =='\\'){
-
ret[index++] = cache[0];
-
ret[index++] = cache[1];
-
cache[0] = '\0';
-
cache[1] = '\0';
-
continue;
-
}
-
if(cache[0] =='/' && cache[1] == '/'){
-
comments = 1;
-
cache[0] = '\0';
-
cache[1] = '\0';
-
continue;
-
}
-
if(cache[0] =='/' && cache[1] == '*'){
-
comments = 2;
-
cache[0] = '\0';
-
cache[1] = '\0';
-
continue;
-
}
-
ret[index++] = cache[0];
-
cache[0]=cache[1];
-
cache[1]='\0';
-
-
}
-
}
-
if(comments == 0){
-
ret[index++] = cache[0];
-
ret[index++] = cache[1];
-
-
}
-
ret[index] = '\0';
-
return ret;
-
}
-
-
int main(){
-
char* test = "I just for test /*test*/ test";
-
char* test1 = "I just for test //comments \ntest";
-
char* test2 = "I just for test \\///comments";
-
printf("%s \n", filter(test));
-
printf("%s \n", filter(test1));
-
printf("%s \n", filter(test2));
-
}
阅读(3267) | 评论(0) | 转发(1) |