一道题目,输入是一个正确的C/C++源程序,输出是将所有注释去掉之后的程序。不细想觉得很简单,字符串搜索,找到//后再找一个回车,删掉,找到/*后再找一个*/,删掉,还有什么好做的,太简单了。 给个测试例子: #include "stdafx.h"#include <iostream>using namespace std; int main(){ cout<<"line 1 // hello"<<endl; // line 1 cout<<"line 2 /* haha~ */"<<endl; // line 2 cout<<"line 3 \" /* hehe */"<<endl; /* line 3 */ /* ********\\\\\\\\\\/////////******** this is test program this is test program this is test program */ return 0;} 这是正确的C++程序,它的输出要是: #include "stdafx.h"#include <iostream>using namespace std; int main(){ cout<<"line 1 // hello"<<endl; cout<<"line 2 /* haha~ */"<<endl; cout<<"line 3 \" /* hehe */"<<endl; return 0;} 哇,这么一来想想就觉得复杂,字符串,先要找到字符串,字符串里的不算,字符串里还有转义符。。。 用状态机做会不会很方便,输入集中比较特殊的就这几个:/,*,",\,关键是在它的构造,在本子上画个表,纵向是表示状态,横向表示特殊的输入,表中的值就是状态的变化,再在旁边记录各个状态的含义,它大概是这样: \输入 / * " \ 回车 其它状态0 1 0 5 0 0 012... 0: 正在分析1:读到第一个/2:读完第二个/,"//...3:读到 "/*...4:读到 "/*...*5:读到第一个"6:读到字符串里的转义符 "...\7:找到注释 0和7是等价的状态,但是可以用7状态做些特别的事情,比如这个时候删除刚找到的注释等。最后的程序如下,输入输出还是用C的文件比较方便: #include "stdio.h"#include "string" char fsm[8][128]; void initfsm(){ const int line_len=sizeof(char)*128; memset(fsm[0],0,line_len); memset(fsm[1],0,line_len); memset(fsm[2],2,line_len); memset(fsm[3],3,line_len); memset(fsm[4],3,line_len); memset(fsm[5],5,line_len); memset(fsm[6],5,line_len); memset(fsm[7],0,line_len); fsm[0]['/']=1; fsm[0]['"']=5; fsm[1]['/']=2; fsm[1]['*']=3; fsm[1]['"']=5; fsm[2]['\n']=7; fsm[3]['*']=4; fsm[4]['/']=7; fsm[4]['*']=4; fsm[5]['"']=0; fsm[5]['\\']=6; fsm[7]['/']=1; fsm[7]['"']=5;} int main(){ int state=0; char c; std::string s; FILE *fin=fopen("e:\\in.txt","r"); FILE *fout=fopen("e:\\out.txt","w"); initfsm(); while(fscanf(fin,"%c",&c)!=EOF) { state=fsm[state][c]; s+=c; switch(state) { case 0: fprintf(fout,"%s",s.c_str()); s=""; break; case 7: s=""; if(c=='\n') { fputc(c,fout); } break; } } fclose(fin); fclose(fout); return 0; }

评论