使用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));
- }