刪除C語言程式中所有的備註陳述式,代碼實現,語言程式注釋
原文連結:http://lixing123.com/archives/310
學習《C程式設計語言》到第1章最後,有一道題目:
編寫一個刪除C語言程式中所有的備註陳述式。要正確處理帶引號的字串與字元常量。在C語言中,注釋不允許嵌套。Exercise 1-23. Write a program to remove all comments from a C program. Don't forget to handle quoted strings and character constants properly. C comments don't nest.
剛開始,我用一種brute-force的方式,對每個字元進行遍曆,然後進行判斷,有沒有進入注釋。
這樣做有一個非常麻煩的問題:只有連續檢測到“//”或者"/*"時,才確定進入了注釋狀態;如果我們只檢測到1個"/",後面就是其它字串的話,還得將這個單獨的"/"列印出來。
而且有許多的分支狀態,如果用if/else的話,會難以理解,並容易出錯。
在網上搜了一下,發現有一種解法非常好:狀態機器。在各種狀態之間跳轉,邏輯清晰,不易出錯,出錯了也容易調試。
下面把代碼貼出來:
#include <stdio.h>int state;int c1,c2;void change_state(int c);int main(int argc, const char * argv[]) { int c; state = 0; c1 = 0; c2 = 0; while ((c=getchar())!=EOF) { c1 = c2; c2 = c; change_state(c); } if (/* DISABLES CODE */ (0)==1) { printf("just test://abcd"); printf("just test:/*hello*/"); }}/*狀態機器函數*/void change_state(int c){ if (state==0) {//普通狀態 if (c=='/') { state = 1; }else if (c=='"'){ state = 5; putchar(c); }else if (c=='\''){ state = 6; putchar(c); } else{ state = 0; putchar(c); } }else if (state==1) {//檢測到1個'/' if (c=='/') { state = 2; }else if (c=='*'){ state = 3; }else{ state = 0; putchar(c1); putchar(c); } }else if (state==2) {// "//"注釋狀態 if (c=='\n') { state = 0; putchar(c); }else{ state = 2; } }else if (state==3) {// "/*"注釋狀態 if (c=='*') { state = 4; }else{ state = 3; } }else if (state==4) { if (c=='/') { state = 0; }else{ state = 3; } }else if (state==5){//在"字串裡 if (c=='"') { state = 0; putchar(c); }else if(c=='\\'){ state = 7; putchar(c); }else{ state = 5; putchar(c); } }else if (state==6){//在'字元裡 if (c=='\'') { state = 0; putchar(c); }else if(c=='\\'){ state = 8; putchar(c); }else{ state = 6; putchar(c); } }else if (state==7){//在"字串裡的"\" state = 5; putchar(c); }else if (state==8){//在'字串裡的"\" state = 6; putchar(c); }}
以本段代碼作為輸入,結果如下:
#include <stdio.h>int state;int c1,c2;void change_state(int c);int main(int argc, const char * argv[]) { int c; state = 0; c1 = 0; c2 = 0; while ((c=getchar())!=EOF) { c1 = c2; c2 = c; change_state(c); } if ( (0)==1) { printf("just test://abcd"); printf("just test:/*hello*/"); }}void change_state(int c){ if (state==0) { if (c=='/') { state = 1; }else if (c=='"'){ state = 5; putchar(c); }else if (c=='\''){ state = 6; putchar(c); } else{ state = 0; putchar(c); } }else if (state==1) { if (c=='/') { state = 2; }else if (c=='*'){ state = 3; }else{ state = 0; putchar(c1); putchar(c); } }else if (state==2) { if (c=='\n') { state = 0; putchar(c); }else{ state = 2; } }else if (state==3) { if (c=='*') { state = 4; }else{ state = 3; } }else if (state==4) { if (c=='/') { state = 0; }else{ state = 3; } }else if (state==5){ if (c=='"') { state = 0; putchar(c); }else if(c=='\\'){ state = 7; putchar(c); }else{ state = 5; putchar(c); } }else if (state==6){ if (c=='\'') { state = 0; putchar(c); }else if(c=='\\'){ state = 8; putchar(c); }else{ state = 6; putchar(c); } }else if (state==7){ state = 5; putchar(c); }else if (state==8){ state = 6; putchar(c); }perfect!
感謝@roma823 及其文章:http://blog.csdn.net/roma823/article/details/6364849