要求:將C++源代碼中的註釋去掉
即,對於下列源代碼
using namespace std;
/* comment 2
// #include <string> */ int main( int argc,char *argv[] /*comment 3*/ )
{
return 1;
}
處理後應輸出
using namespace std;
int main(int argc, char * argv[])
{
return 1;
}
函數原型: void foo( const char * src,char * buf, unsigned char * buf_len);
其中src爲源代碼緩衝區,buf爲輸出緩衝區,buf_len爲輸出緩衝區的長度,又已知源代碼長度不會超過1M。
編程思路很簡單,基於一個簡單的三狀態的有窮自動機即可。foo()函數在執行過程中將在三種狀態中進行轉換:代碼、舊式註釋(//)和新式註釋(/* */ )。三種狀態之間的轉換件如下
當處於代碼狀態時,如果後續兩個字符爲'//',則進入舊式註釋;若後續兩個字符爲'/*',則進入新式註釋;否則保持當前狀態,並將下一個字符複製進輸出緩衝區。三種情況下都要對讀指針進行相應的調整。
當處於舊式註釋狀態時,如果下一個字符爲'/n'(換行符),則進入代碼狀態,並且將'/n'也複製進輸出緩衝區;否則仍保持當前狀態。兩種情況下都要對讀指針進行相應的調整。
當處於新式註釋狀態時,如果下兩個字符爲'*/',則進入代碼狀態;否則保持當前狀態。兩種情況下都要對讀指針進行相應的調整。
實現代碼如下:
#include <fstream>
using namespace std;
const char STAR='*';
const char SLASH='/';
const char NEWLINE=' ';
const unsigned int MAX=1048576;
enum State
{
CODE,
OLD_STYLE,
NEW_STYLE,
};
void foo(const char * src,char * buf, unsigned int buf_len)
{
State state=CODE;
const char * ptr= src;
unsigned int count=0;
while( count<(buf_len-1)
&& count<MAX
)
{
switch(state)
{
case CODE:
if( *ptr==SLASH && *(ptr+1)==SLASH)
{
state=OLD_STYLE;
ptr+=2;
}
else if( *ptr==SLASH && *(ptr+1)==STAR)
{
state=NEW_STYLE;
ptr+2;
}
else
{
buf[count++]=*ptr;
ptr++;
}
break; //end of case CODE
case OLD_STYLE:
if( *ptr==NEWLINE)
{
state=CODE;
buf[count++]=*ptr; //注意這裏不要在輸出中遺漏換行符
ptr++;
}
else
{
ptr++;
}
break;//end of case OLD_STYLE
case NEW_STYLE:
if( *ptr==STAR && *(ptr+1)==SLASH)
{
state=CODE;
//如果註釋結束緊接着換行符的話,要跳過這個換行符
if( *(ptr+2)==NEWLINE )
ptr+=3;
else
ptr+=2;
}
else
{
ptr++;
}
break;// end of case NEW_STYLE
default:
cout<<"Oh,should not happen!"<<endl;
} //end of switch
}// end of while
buf[count++]='';
return ;
}
int main(int argc,char *argv[])
{
char source[MAX]= {'',};
char stripped[MAX]= {'',};
ifstream original_file("input");
original_file.read(source,MAX);
foo ( source,stripped,sizeof(source));
ofstream stripped_file("output");
stripped_file.write(stripped,strlen(stripped));
original_file.close();
stripped_file.close();
return 1;
}